xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/function-tests.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
13ad841b2Smrg /* Unit tests for function-handling.
2*4c3eb207Smrg    Copyright (C) 2015-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 "tm.h"
243ad841b2Smrg #include "opts.h"
253ad841b2Smrg #include "hash-set.h"
263ad841b2Smrg #include "fixed-value.h"
273ad841b2Smrg #include "alias.h"
283ad841b2Smrg #include "flags.h"
293ad841b2Smrg #include "symtab.h"
303ad841b2Smrg #include "tree-core.h"
313ad841b2Smrg #include "stor-layout.h"
323ad841b2Smrg #include "tree.h"
333ad841b2Smrg #include "stringpool.h"
343ad841b2Smrg #include "stor-layout.h"
353ad841b2Smrg #include "rtl.h"
363ad841b2Smrg #include "predict.h"
373ad841b2Smrg #include "vec.h"
383ad841b2Smrg #include "hashtab.h"
393ad841b2Smrg #include "hash-set.h"
403ad841b2Smrg #include "hard-reg-set.h"
413ad841b2Smrg #include "input.h"
423ad841b2Smrg #include "function.h"
433ad841b2Smrg #include "dominance.h"
443ad841b2Smrg #include "cfg.h"
453ad841b2Smrg #include "cfganal.h"
463ad841b2Smrg #include "basic-block.h"
473ad841b2Smrg #include "tree-ssa-alias.h"
483ad841b2Smrg #include "internal-fn.h"
493ad841b2Smrg #include "gimple-fold.h"
503ad841b2Smrg #include "gimple-expr.h"
513ad841b2Smrg #include "toplev.h"
523ad841b2Smrg #include "print-tree.h"
533ad841b2Smrg #include "tree-iterator.h"
543ad841b2Smrg #include "gimplify.h"
553ad841b2Smrg #include "tree-cfg.h"
563ad841b2Smrg #include "basic-block.h"
573ad841b2Smrg #include "alias.h"
583ad841b2Smrg #include "symtab.h"
593ad841b2Smrg #include "inchash.h"
603ad841b2Smrg #include "tree.h"
613ad841b2Smrg #include "fold-const.h"
623ad841b2Smrg #include "stor-layout.h"
633ad841b2Smrg #include "stmt.h"
643ad841b2Smrg #include "hash-table.h"
653ad841b2Smrg #include "tree-ssa-alias.h"
663ad841b2Smrg #include "internal-fn.h"
673ad841b2Smrg #include "gimple-expr.h"
683ad841b2Smrg #include "is-a.h"
693ad841b2Smrg #include "gimple.h"
703ad841b2Smrg #include "tree-pass.h"
713ad841b2Smrg #include "context.h"
723ad841b2Smrg #include "hash-map.h"
733ad841b2Smrg #include "plugin-api.h"
743ad841b2Smrg #include "ipa-ref.h"
753ad841b2Smrg #include "cgraph.h"
763ad841b2Smrg #include "selftest.h"
773ad841b2Smrg #include "print-rtl.h"
783ad841b2Smrg 
793ad841b2Smrg #if CHECKING_P
803ad841b2Smrg 
813ad841b2Smrg namespace selftest {
823ad841b2Smrg 
833ad841b2Smrg /* Helper function for selftests of function-creation.  */
843ad841b2Smrg 
85*4c3eb207Smrg tree
make_fndecl(tree return_type,const char * name,vec<tree> & param_types,bool is_variadic)863ad841b2Smrg make_fndecl (tree return_type,
873ad841b2Smrg 	     const char *name,
883ad841b2Smrg 	     vec <tree> &param_types,
89*4c3eb207Smrg 	     bool is_variadic)
903ad841b2Smrg {
913ad841b2Smrg   tree fn_type;
923ad841b2Smrg   if (is_variadic)
933ad841b2Smrg     fn_type = build_varargs_function_type_array (return_type,
943ad841b2Smrg 						 param_types.length (),
953ad841b2Smrg 						 param_types.address ());
963ad841b2Smrg   else
973ad841b2Smrg     fn_type = build_function_type_array (return_type,
983ad841b2Smrg 					 param_types.length (),
993ad841b2Smrg 					 param_types.address ());
1003ad841b2Smrg   /* FIXME: this uses input_location: */
1013ad841b2Smrg   tree fndecl = build_fn_decl (name, fn_type);
1023ad841b2Smrg 
1033ad841b2Smrg   return fndecl;
1043ad841b2Smrg }
1053ad841b2Smrg 
1063ad841b2Smrg /* Verify creating a function declaration equivalent to the following
1073ad841b2Smrg      int test_fndecl_int_void (void);
1083ad841b2Smrg    C declaration.  */
1093ad841b2Smrg 
1103ad841b2Smrg static void
test_fndecl_int_void()1113ad841b2Smrg test_fndecl_int_void ()
1123ad841b2Smrg {
1133ad841b2Smrg   auto_vec <tree> param_types;
1143ad841b2Smrg   const char *name = "test_fndecl_int_void";
1153ad841b2Smrg   tree fndecl = make_fndecl (integer_type_node,
1163ad841b2Smrg 			     name,
1173ad841b2Smrg 			     param_types);
1183ad841b2Smrg   ASSERT_TRUE (fndecl != NULL);
1193ad841b2Smrg 
1203ad841b2Smrg   /* Verify name of decl.  */
1213ad841b2Smrg   tree declname = DECL_NAME (fndecl);
1223ad841b2Smrg   ASSERT_TRUE (declname != NULL);
1233ad841b2Smrg   ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (declname));
1243ad841b2Smrg   /* We expect it to use a *copy* of the string we passed in.  */
1253ad841b2Smrg   const char *identifier_ptr = IDENTIFIER_POINTER (declname);
1263ad841b2Smrg   ASSERT_NE (name, identifier_ptr);
1273ad841b2Smrg   ASSERT_EQ (0, strcmp ("test_fndecl_int_void", identifier_ptr));
1283ad841b2Smrg 
1293ad841b2Smrg   /* Verify type of fndecl.  */
1303ad841b2Smrg   ASSERT_EQ (FUNCTION_DECL, TREE_CODE (fndecl));
1313ad841b2Smrg   tree fntype = TREE_TYPE (fndecl);
1323ad841b2Smrg   ASSERT_EQ (FUNCTION_TYPE, TREE_CODE (fntype));
1333ad841b2Smrg 
1343ad841b2Smrg   /* Verify return type.  */
1353ad841b2Smrg   ASSERT_EQ (integer_type_node, TREE_TYPE (fntype));
1363ad841b2Smrg 
1373ad841b2Smrg   /* Verify "void" args.  */
1383ad841b2Smrg   tree argtypes = TYPE_ARG_TYPES (fntype);
1393ad841b2Smrg   ASSERT_EQ (TREE_LIST, TREE_CODE (argtypes));
1403ad841b2Smrg   ASSERT_EQ (void_type_node, TREE_VALUE (argtypes));
1413ad841b2Smrg   ASSERT_EQ (NULL, TREE_CHAIN (argtypes));
1423ad841b2Smrg }
1433ad841b2Smrg 
1443ad841b2Smrg /* Verify creating a function declaration equivalent to the following
1453ad841b2Smrg      float test_fndecl_float_intchar (int, char);
1463ad841b2Smrg    C declaration.  */
1473ad841b2Smrg 
1483ad841b2Smrg static void
test_fndecl_float_intchar()1493ad841b2Smrg test_fndecl_float_intchar ()
1503ad841b2Smrg {
1513ad841b2Smrg   auto_vec <tree> param_types;
1523ad841b2Smrg   param_types.safe_push (integer_type_node);
1533ad841b2Smrg   param_types.safe_push (char_type_node);
1543ad841b2Smrg   const char *name = "test_fndecl_float_intchar";
1553ad841b2Smrg   tree fndecl = make_fndecl (float_type_node,
1563ad841b2Smrg 			     name,
1573ad841b2Smrg 			     param_types);
1583ad841b2Smrg   ASSERT_TRUE (fndecl != NULL);
1593ad841b2Smrg 
1603ad841b2Smrg   /* Verify name of decl.  */
1613ad841b2Smrg   tree declname = DECL_NAME (fndecl);
1623ad841b2Smrg   ASSERT_TRUE (declname != NULL);
1633ad841b2Smrg   ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (declname));
1643ad841b2Smrg   /* We expect it to use a *copy* of the string we passed in.  */
1653ad841b2Smrg   const char *identifier_ptr = IDENTIFIER_POINTER (declname);
1663ad841b2Smrg   ASSERT_NE (name, identifier_ptr);
1673ad841b2Smrg   ASSERT_EQ (0, strcmp (name, identifier_ptr));
1683ad841b2Smrg 
1693ad841b2Smrg   /* Verify type of fndecl.  */
1703ad841b2Smrg   ASSERT_EQ (FUNCTION_DECL, TREE_CODE (fndecl));
1713ad841b2Smrg   tree fntype = TREE_TYPE (fndecl);
1723ad841b2Smrg   ASSERT_EQ (FUNCTION_TYPE, TREE_CODE (fntype));
1733ad841b2Smrg 
1743ad841b2Smrg   /* Verify return type.  */
1753ad841b2Smrg   ASSERT_EQ (float_type_node, TREE_TYPE (fntype));
1763ad841b2Smrg 
1773ad841b2Smrg   /* Verify "(int, char)" args.  */
1783ad841b2Smrg   tree arg0 = TYPE_ARG_TYPES (fntype);
1793ad841b2Smrg   ASSERT_EQ (TREE_LIST, TREE_CODE (arg0));
1803ad841b2Smrg   ASSERT_EQ (integer_type_node, TREE_VALUE (arg0));
1813ad841b2Smrg   tree arg1 = TREE_CHAIN (arg0);
1823ad841b2Smrg   ASSERT_TRUE (arg1 != NULL);
1833ad841b2Smrg   ASSERT_EQ (TREE_LIST, TREE_CODE (arg1));
1843ad841b2Smrg   ASSERT_EQ (char_type_node, TREE_VALUE (arg1));
1853ad841b2Smrg   tree argterm = TREE_CHAIN (arg1);
1863ad841b2Smrg   ASSERT_TRUE (argterm != NULL);
1873ad841b2Smrg   ASSERT_EQ (TREE_LIST, TREE_CODE (argterm));
1883ad841b2Smrg   ASSERT_EQ (void_type_node, TREE_VALUE (argterm));
1893ad841b2Smrg   ASSERT_EQ (NULL, TREE_CHAIN (argterm));
1903ad841b2Smrg }
1913ad841b2Smrg 
1923ad841b2Smrg /* The test cases using these helper functions take a trivial function:
1933ad841b2Smrg 
1943ad841b2Smrg      int test_fn (void) { return 42; }
1953ad841b2Smrg 
1963ad841b2Smrg    and test various conversions done to it:
1973ad841b2Smrg 
1983ad841b2Smrg    - gimplification
1993ad841b2Smrg    - construction of the CFG
2003ad841b2Smrg    - conversion to SSA form
2013ad841b2Smrg    - expansion to RTL form
2023ad841b2Smrg 
2033ad841b2Smrg    In avoid having one overlong test case, this is broken
2043ad841b2Smrg    up into separate test cases for each stage, with helper functions
2053ad841b2Smrg    to minimize code duplication.
2063ad841b2Smrg 
2073ad841b2Smrg    Another approach would be to attempt to directly construct a function
2083ad841b2Smrg    in the appropriate representation at each stage, though presumably
2093ad841b2Smrg    that would exhibit different kinds of failure compared to this
2103ad841b2Smrg    approach.  */
2113ad841b2Smrg 
2123ad841b2Smrg /* Construct this function:
2133ad841b2Smrg    int test_fn (void) { return 42; }
2143ad841b2Smrg    in generic tree form.  Return the fndecl.  */
2153ad841b2Smrg 
2163ad841b2Smrg static tree
build_trivial_generic_function()2173ad841b2Smrg build_trivial_generic_function ()
2183ad841b2Smrg {
2193ad841b2Smrg   auto_vec <tree> param_types;
2203ad841b2Smrg   tree fndecl = make_fndecl (integer_type_node,
2213ad841b2Smrg 			     "test_fn",
2223ad841b2Smrg 			     param_types);
2233ad841b2Smrg   ASSERT_TRUE (fndecl != NULL);
2243ad841b2Smrg 
2253ad841b2Smrg   /* Populate the function.  */
2263ad841b2Smrg   tree retval = build_decl (UNKNOWN_LOCATION, RESULT_DECL,
2273ad841b2Smrg 			    NULL_TREE, integer_type_node);
2283ad841b2Smrg   DECL_ARTIFICIAL (retval) = 1;
2293ad841b2Smrg   DECL_IGNORED_P (retval) = 1;
2303ad841b2Smrg   DECL_RESULT (fndecl) = retval;
2313ad841b2Smrg 
2323ad841b2Smrg   /* Create a BIND_EXPR, and within it, a statement list.  */
2333ad841b2Smrg   tree stmt_list = alloc_stmt_list ();
2343ad841b2Smrg   tree_stmt_iterator stmt_iter = tsi_start (stmt_list);
2353ad841b2Smrg   tree block = make_node (BLOCK);
2363ad841b2Smrg   tree bind_expr
2373ad841b2Smrg     = build3 (BIND_EXPR, void_type_node, NULL, stmt_list, block);
2383ad841b2Smrg 
2393ad841b2Smrg   tree modify_retval = build2 (MODIFY_EXPR,
2403ad841b2Smrg 			       integer_type_node,
2413ad841b2Smrg 			       retval,
2423ad841b2Smrg 			       build_int_cst (integer_type_node, 42));
2433ad841b2Smrg   tree return_stmt = build1 (RETURN_EXPR,
2443ad841b2Smrg 			     integer_type_node,
2453ad841b2Smrg 			     modify_retval);
2463ad841b2Smrg   tsi_link_after (&stmt_iter, return_stmt, TSI_CONTINUE_LINKING);
2473ad841b2Smrg 
2483ad841b2Smrg   DECL_INITIAL (fndecl) = block;
2493ad841b2Smrg   BLOCK_SUPERCONTEXT (block) = fndecl;
2503ad841b2Smrg 
2513ad841b2Smrg   /* how to add to function? the following appears to be how to
2523ad841b2Smrg      set the body of a fndecl: */
2533ad841b2Smrg   DECL_SAVED_TREE(fndecl) = bind_expr;
2543ad841b2Smrg 
2553ad841b2Smrg   /* Ensure that locals appear in the debuginfo.  */
2563ad841b2Smrg   BLOCK_VARS (block) = BIND_EXPR_VARS (bind_expr);
2573ad841b2Smrg 
2583ad841b2Smrg   return fndecl;
2593ad841b2Smrg }
2603ad841b2Smrg 
2613ad841b2Smrg /* Construct this function:
2623ad841b2Smrg      int test_fn (void) { return 42; }
2633ad841b2Smrg    in "high gimple" form.  Return the fndecl.  */
2643ad841b2Smrg 
2653ad841b2Smrg static tree
build_trivial_high_gimple_function()2663ad841b2Smrg build_trivial_high_gimple_function ()
2673ad841b2Smrg {
2683ad841b2Smrg   /* Construct a trivial function, and gimplify it: */
2693ad841b2Smrg   tree fndecl = build_trivial_generic_function ();
2703ad841b2Smrg   gimplify_function_tree (fndecl);
2713ad841b2Smrg   return fndecl;
2723ad841b2Smrg }
2733ad841b2Smrg 
2743ad841b2Smrg /* Build a CFG for a function in gimple form.  */
2753ad841b2Smrg 
2763ad841b2Smrg static void
build_cfg(tree fndecl)2773ad841b2Smrg build_cfg (tree fndecl)
2783ad841b2Smrg {
2793ad841b2Smrg   function *fun = DECL_STRUCT_FUNCTION (fndecl);
2803ad841b2Smrg   ASSERT_TRUE (fun != NULL);
2813ad841b2Smrg   ASSERT_EQ (fndecl, fun->decl);
2823ad841b2Smrg 
2833ad841b2Smrg   /* We first have to lower control flow; for our trivial test function
2843ad841b2Smrg      this gives us:
2853ad841b2Smrg 	 test_fn ()
2863ad841b2Smrg 	 {
2873ad841b2Smrg 	   D.56 = 42;
2883ad841b2Smrg 	   goto <D.57>;
2893ad841b2Smrg 	   <D.57>:
2903ad841b2Smrg 	   return D.56;
2913ad841b2Smrg 	 }
2923ad841b2Smrg   */
2933ad841b2Smrg   gimple_opt_pass *lower_cf_pass = make_pass_lower_cf (g);
2943ad841b2Smrg   push_cfun (fun);
2953ad841b2Smrg   lower_cf_pass->execute (fun);
2963ad841b2Smrg   pop_cfun ();
2973ad841b2Smrg   delete lower_cf_pass;
2983ad841b2Smrg 
2993ad841b2Smrg   /* We can now convert to CFG form; for our trivial test function this
3003ad841b2Smrg      gives us:
3013ad841b2Smrg 	 test_fn ()
3023ad841b2Smrg 	 {
3033ad841b2Smrg 	   <bb 2>:
3043ad841b2Smrg 	   D.56 = 42;
3053ad841b2Smrg 	   return D.56;
3063ad841b2Smrg 	 }
3073ad841b2Smrg   */
3083ad841b2Smrg   gimple_opt_pass *build_cfg_pass = make_pass_build_cfg (g);
3093ad841b2Smrg   push_cfun (fun);
3103ad841b2Smrg   build_cfg_pass->execute (fun);
3113ad841b2Smrg   pop_cfun ();
3123ad841b2Smrg   delete build_cfg_pass;
3133ad841b2Smrg }
3143ad841b2Smrg 
3153ad841b2Smrg /* Convert a gimple+CFG function to SSA form.  */
3163ad841b2Smrg 
3173ad841b2Smrg static void
convert_to_ssa(tree fndecl)3183ad841b2Smrg convert_to_ssa (tree fndecl)
3193ad841b2Smrg {
3203ad841b2Smrg   function *fun = DECL_STRUCT_FUNCTION (fndecl);
3213ad841b2Smrg   ASSERT_TRUE (fun != NULL);
3223ad841b2Smrg   ASSERT_EQ (fndecl, fun->decl);
3233ad841b2Smrg 
3243ad841b2Smrg   gimple_opt_pass *build_ssa_pass = make_pass_build_ssa (g);
3253ad841b2Smrg   push_cfun (fun);
3263ad841b2Smrg   build_ssa_pass->execute (fun);
3273ad841b2Smrg   pop_cfun ();
3283ad841b2Smrg   delete build_ssa_pass;
3293ad841b2Smrg }
3303ad841b2Smrg 
3313ad841b2Smrg /* Assuming we have a simple 3-block CFG like this:
3323ad841b2Smrg      [ENTRY] -> [block2] -> [EXIT]
3333ad841b2Smrg    get the "real" basic block (block 2).  */
3343ad841b2Smrg 
3353ad841b2Smrg static basic_block
get_real_block(function * fun)3363ad841b2Smrg get_real_block (function *fun)
3373ad841b2Smrg {
3383ad841b2Smrg   ASSERT_TRUE (fun->cfg != NULL);
3393ad841b2Smrg   ASSERT_EQ (3, n_basic_blocks_for_fn (fun));
3403ad841b2Smrg   basic_block bb2 = (*fun->cfg->x_basic_block_info)[2];
3413ad841b2Smrg   ASSERT_TRUE (bb2 != NULL);
3423ad841b2Smrg   return bb2;
3433ad841b2Smrg }
3443ad841b2Smrg 
3453ad841b2Smrg /* Verify that we have a simple 3-block CFG: the two "fake" ones, and
3463ad841b2Smrg    a "real" one:
3473ad841b2Smrg      [ENTRY] -> [block2] -> [EXIT].  */
3483ad841b2Smrg 
3493ad841b2Smrg static void
verify_three_block_cfg(function * fun)3503ad841b2Smrg verify_three_block_cfg (function *fun)
3513ad841b2Smrg {
3523ad841b2Smrg   ASSERT_TRUE (fun->cfg != NULL);
3533ad841b2Smrg   ASSERT_EQ (3, n_basic_blocks_for_fn (fun));
3543ad841b2Smrg   ASSERT_EQ (2, n_edges_for_fn (fun));
3553ad841b2Smrg 
3563ad841b2Smrg   /* The "fake" basic blocks.  */
3573ad841b2Smrg   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
3583ad841b2Smrg   ASSERT_TRUE (entry != NULL);
3593ad841b2Smrg   ASSERT_EQ (ENTRY_BLOCK, entry->index);
3603ad841b2Smrg 
3613ad841b2Smrg   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
3623ad841b2Smrg   ASSERT_TRUE (exit != NULL);
3633ad841b2Smrg   ASSERT_EQ (EXIT_BLOCK, exit->index);
3643ad841b2Smrg 
3653ad841b2Smrg   /* The "real" basic block.  */
3663ad841b2Smrg   basic_block bb2 = get_real_block (fun);
3673ad841b2Smrg   ASSERT_TRUE (bb2 != NULL);
3683ad841b2Smrg   ASSERT_EQ (2, bb2->index);
3693ad841b2Smrg 
3703ad841b2Smrg   /* Verify connectivity.  */
3713ad841b2Smrg   ASSERT_EQ (NULL, entry->preds);
3723ad841b2Smrg   ASSERT_EQ (1, entry->succs->length ());
3733ad841b2Smrg 
3743ad841b2Smrg   edge from_entry_to_bb2 = (*entry->succs)[0];
3753ad841b2Smrg   ASSERT_EQ (entry, from_entry_to_bb2->src);
3763ad841b2Smrg   ASSERT_EQ (bb2, from_entry_to_bb2->dest);
3773ad841b2Smrg 
3783ad841b2Smrg   ASSERT_EQ (1, bb2->preds->length ());
3793ad841b2Smrg   ASSERT_EQ (from_entry_to_bb2, (*bb2->preds)[0]);
3803ad841b2Smrg   ASSERT_EQ (1, bb2->succs->length ());
3813ad841b2Smrg 
3823ad841b2Smrg   edge from_bb2_to_exit = (*bb2->succs)[0];
3833ad841b2Smrg   ASSERT_EQ (bb2, from_bb2_to_exit->src);
3843ad841b2Smrg   ASSERT_EQ (exit, from_bb2_to_exit->dest);
3853ad841b2Smrg 
3863ad841b2Smrg   ASSERT_EQ (1, exit->preds->length ());
3873ad841b2Smrg   ASSERT_EQ (from_bb2_to_exit, (*exit->preds)[0]);
3883ad841b2Smrg   ASSERT_EQ (NULL, exit->succs);
3893ad841b2Smrg }
3903ad841b2Smrg 
3913ad841b2Smrg /* As above, but additionally verify the gimple statements are sane.  */
3923ad841b2Smrg 
3933ad841b2Smrg static void
verify_three_block_gimple_cfg(function * fun)3943ad841b2Smrg verify_three_block_gimple_cfg (function *fun)
3953ad841b2Smrg {
3963ad841b2Smrg   verify_three_block_cfg (fun);
3973ad841b2Smrg 
3983ad841b2Smrg   /* The "fake" basic blocks should be flagged as gimple, but with have no
3993ad841b2Smrg      statements.  */
4003ad841b2Smrg   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
4013ad841b2Smrg   ASSERT_TRUE (entry != NULL);
4023ad841b2Smrg   ASSERT_EQ (0, entry->flags & BB_RTL);
4033ad841b2Smrg   ASSERT_EQ (NULL, bb_seq (entry));
4043ad841b2Smrg 
4053ad841b2Smrg   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
4063ad841b2Smrg   ASSERT_TRUE (exit != NULL);
4073ad841b2Smrg   ASSERT_EQ (0, entry->flags & BB_RTL);
4083ad841b2Smrg   ASSERT_EQ (NULL, bb_seq (exit));
4093ad841b2Smrg 
4103ad841b2Smrg   /* The "real" basic block should be flagged as gimple, and have one
4113ad841b2Smrg      or more statements.  */
4123ad841b2Smrg   basic_block bb2 = get_real_block (fun);
4133ad841b2Smrg   ASSERT_TRUE (bb2 != NULL);
4143ad841b2Smrg   ASSERT_EQ (0, entry->flags & BB_RTL);
4153ad841b2Smrg   ASSERT_TRUE (bb_seq (bb2) != NULL);
4163ad841b2Smrg }
4173ad841b2Smrg 
4183ad841b2Smrg /* As above, but additionally verify the RTL insns are sane.  */
4193ad841b2Smrg 
4203ad841b2Smrg void
verify_three_block_rtl_cfg(function * fun)4213ad841b2Smrg verify_three_block_rtl_cfg (function *fun)
4223ad841b2Smrg {
4233ad841b2Smrg   verify_three_block_cfg (fun);
4243ad841b2Smrg 
4253ad841b2Smrg   /* The "fake" basic blocks should be flagged as RTL, but with no
4263ad841b2Smrg      insns.  */
4273ad841b2Smrg   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
4283ad841b2Smrg   ASSERT_TRUE (entry != NULL);
4293ad841b2Smrg   ASSERT_EQ (BB_RTL, entry->flags & BB_RTL);
4303ad841b2Smrg   ASSERT_EQ (NULL, BB_HEAD (entry));
4313ad841b2Smrg 
4323ad841b2Smrg   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
4333ad841b2Smrg   ASSERT_TRUE (exit != NULL);
4343ad841b2Smrg   ASSERT_EQ (BB_RTL, exit->flags & BB_RTL);
4353ad841b2Smrg   ASSERT_EQ (NULL, BB_HEAD (exit));
4363ad841b2Smrg 
4373ad841b2Smrg   /* The "real" basic block should be flagged as RTL, and have one
4383ad841b2Smrg      or more insns.  */
4393ad841b2Smrg   basic_block bb2 = get_real_block (fun);
4403ad841b2Smrg   ASSERT_TRUE (bb2 != NULL);
4413ad841b2Smrg   ASSERT_EQ (BB_RTL, bb2->flags & BB_RTL);
4423ad841b2Smrg   ASSERT_TRUE (BB_HEAD (bb2) != NULL);
4433ad841b2Smrg }
4443ad841b2Smrg 
4453ad841b2Smrg /* Test converting our trivial function:
4463ad841b2Smrg      int test_fn (void) { return 42; }
4473ad841b2Smrg    to gimple form.  */
4483ad841b2Smrg 
4493ad841b2Smrg static void
test_gimplification()4503ad841b2Smrg test_gimplification ()
4513ad841b2Smrg {
4523ad841b2Smrg   tree fndecl = build_trivial_generic_function ();
4533ad841b2Smrg 
4543ad841b2Smrg   /* Convert to gimple: */
4553ad841b2Smrg   gimplify_function_tree (fndecl);
4563ad841b2Smrg 
4573ad841b2Smrg   /* Verify that we got gimple out of it.  */
4583ad841b2Smrg 
4593ad841b2Smrg   /* The function is now in GIMPLE form but the CFG has not been
4603ad841b2Smrg      built yet.  */
4613ad841b2Smrg 
4623ad841b2Smrg   /* We should have a struct function for the decl.  */
4633ad841b2Smrg   function *fun = DECL_STRUCT_FUNCTION (fndecl);
4643ad841b2Smrg   ASSERT_TRUE (fun != NULL);
4653ad841b2Smrg   ASSERT_EQ (fndecl, fun->decl);
4663ad841b2Smrg 
4673ad841b2Smrg   /* We expect a GIMPLE_BIND, with two gimple statements within it:
4683ad841b2Smrg        tmp = 42;
4693ad841b2Smrg        return tmp;  */
4703ad841b2Smrg 
4713ad841b2Smrg   gimple_seq seq_fn_body = gimple_body (fndecl);
4723ad841b2Smrg   ASSERT_TRUE (seq_fn_body != NULL);
4733ad841b2Smrg   gimple *bind_stmt = gimple_seq_first_stmt (seq_fn_body);
4743ad841b2Smrg   ASSERT_EQ (GIMPLE_BIND, gimple_code (bind_stmt));
4753ad841b2Smrg   ASSERT_EQ (NULL, bind_stmt->next);
4763ad841b2Smrg 
4773ad841b2Smrg   gimple_seq seq_bind_body = gimple_bind_body (as_a <gbind *> (bind_stmt));
4783ad841b2Smrg 
4793ad841b2Smrg   /* Verify that we have the 2 statements we expect.  */
4803ad841b2Smrg   ASSERT_TRUE (seq_bind_body != NULL);
4813ad841b2Smrg   gimple *stmt1 = gimple_seq_first_stmt (seq_bind_body);
4823ad841b2Smrg   ASSERT_TRUE (stmt1 != NULL);
4833ad841b2Smrg   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt1));
4843ad841b2Smrg   gimple *stmt2 = stmt1->next;
4853ad841b2Smrg   ASSERT_TRUE (stmt2 != NULL);
4863ad841b2Smrg   ASSERT_EQ (stmt1, stmt2->prev);
4873ad841b2Smrg   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt2));
4883ad841b2Smrg }
4893ad841b2Smrg 
4903ad841b2Smrg /* Test of building a CFG for a function in high gimple form.  */
4913ad841b2Smrg 
4923ad841b2Smrg static void
test_building_cfg()4933ad841b2Smrg test_building_cfg ()
4943ad841b2Smrg {
4953ad841b2Smrg   /* Construct a trivial function, and gimplify it: */
4963ad841b2Smrg   tree fndecl = build_trivial_high_gimple_function ();
4973ad841b2Smrg   function *fun = DECL_STRUCT_FUNCTION (fndecl);
4983ad841b2Smrg   ASSERT_TRUE (fun != NULL);
4993ad841b2Smrg 
5003ad841b2Smrg   /* Build a CFG.  */
5013ad841b2Smrg   build_cfg (fndecl);
5023ad841b2Smrg 
5033ad841b2Smrg   /* The CFG-building code constructs a 4-block cfg (with
5043ad841b2Smrg      ENTRY and EXIT):
5053ad841b2Smrg        test_fn ()
5063ad841b2Smrg        {
5073ad841b2Smrg          <bb 2>:
5083ad841b2Smrg 	 D.65 = 42;
5093ad841b2Smrg 
5103ad841b2Smrg 	 <bb 3>:
5113ad841b2Smrg 	 return D.65;
5123ad841b2Smrg        }
5133ad841b2Smrg      and then ought to merge blocks 2 and 3 in cleanup_tree_cfg.
5143ad841b2Smrg 
5153ad841b2Smrg      Hence we should end up with a simple 3-block cfg, the two "fake" ones,
5163ad841b2Smrg      and a "real" one:
5173ad841b2Smrg        [ENTRY] -> [block2] -> [EXIT]
5183ad841b2Smrg      with code like this:
5193ad841b2Smrg 	 test_fn ()
5203ad841b2Smrg 	 {
5213ad841b2Smrg 	   <bb 2>:
5223ad841b2Smrg 	   D.56 = 42;
5233ad841b2Smrg 	   return D.56;
5243ad841b2Smrg 	 }
5253ad841b2Smrg   */
5263ad841b2Smrg   verify_three_block_gimple_cfg (fun);
5273ad841b2Smrg 
5283ad841b2Smrg   /* Verify the statements within the "real" block.  */
5293ad841b2Smrg   basic_block bb2 = get_real_block (fun);
5303ad841b2Smrg   gimple *stmt_a = gimple_seq_first_stmt (bb_seq (bb2));
5313ad841b2Smrg   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt_a));
5323ad841b2Smrg   gimple *stmt_b = stmt_a->next;
5333ad841b2Smrg   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt_b));
5343ad841b2Smrg   ASSERT_EQ (NULL, stmt_b->next);
5353ad841b2Smrg }
5363ad841b2Smrg 
5373ad841b2Smrg /* Test of conversion of gimple to SSA form.  */
5383ad841b2Smrg 
5393ad841b2Smrg static void
test_conversion_to_ssa()5403ad841b2Smrg test_conversion_to_ssa ()
5413ad841b2Smrg {
5423ad841b2Smrg   /* As above, construct a trivial function, gimplify it, and build a CFG: */
5433ad841b2Smrg   tree fndecl = build_trivial_high_gimple_function ();
5443ad841b2Smrg   function *fun = DECL_STRUCT_FUNCTION (fndecl);
5453ad841b2Smrg   ASSERT_TRUE (fun != NULL);
5463ad841b2Smrg   build_cfg (fndecl);
5473ad841b2Smrg 
5483ad841b2Smrg   convert_to_ssa (fndecl);
5493ad841b2Smrg 
5503ad841b2Smrg   verify_three_block_gimple_cfg (fun);
5513ad841b2Smrg 
5523ad841b2Smrg   /* For out trivial test function we should now have something like
5533ad841b2Smrg      this:
5543ad841b2Smrg        test_fn ()
5553ad841b2Smrg        {
5563ad841b2Smrg 	 <bb 2>:
5573ad841b2Smrg 	 _1 = 42;
5583ad841b2Smrg 	 return _1;
5593ad841b2Smrg        }
5603ad841b2Smrg   */
5613ad841b2Smrg   basic_block bb2 = get_real_block (fun);
5623ad841b2Smrg   gimple *stmt_a = gimple_seq_first_stmt (bb_seq (bb2));
5633ad841b2Smrg   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt_a));
5643ad841b2Smrg 
5653ad841b2Smrg   gimple *stmt_b = stmt_a->next;
5663ad841b2Smrg   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt_b));
5673ad841b2Smrg   ASSERT_EQ (NULL, stmt_b->next);
5683ad841b2Smrg 
5693ad841b2Smrg   greturn *return_stmt = as_a <greturn *> (stmt_b);
5703ad841b2Smrg   ASSERT_EQ (SSA_NAME, TREE_CODE (gimple_return_retval (return_stmt)));
5713ad841b2Smrg }
5723ad841b2Smrg 
573*4c3eb207Smrg /* Test range folding.  We must start this here because we need cfun
574*4c3eb207Smrg    set.  */
575*4c3eb207Smrg 
576*4c3eb207Smrg static void
test_ranges()577*4c3eb207Smrg test_ranges ()
578*4c3eb207Smrg {
579*4c3eb207Smrg   tree fndecl = build_trivial_high_gimple_function ();
580*4c3eb207Smrg   function *fun = DECL_STRUCT_FUNCTION (fndecl);
581*4c3eb207Smrg   push_cfun (fun);
582*4c3eb207Smrg   range_tests ();
583*4c3eb207Smrg   pop_cfun ();
584*4c3eb207Smrg }
585*4c3eb207Smrg 
5863ad841b2Smrg /* Test of expansion from gimple-ssa to RTL.  */
5873ad841b2Smrg 
5883ad841b2Smrg static void
test_expansion_to_rtl()5893ad841b2Smrg test_expansion_to_rtl ()
5903ad841b2Smrg {
5913ad841b2Smrg   /* As above, construct a trivial function, gimplify it, build a CFG,
5923ad841b2Smrg      and convert to SSA: */
5933ad841b2Smrg   tree fndecl = build_trivial_high_gimple_function ();
5943ad841b2Smrg   function *fun = DECL_STRUCT_FUNCTION (fndecl);
5953ad841b2Smrg   ASSERT_TRUE (fun != NULL);
5963ad841b2Smrg   build_cfg (fndecl);
5973ad841b2Smrg   convert_to_ssa (fndecl);
5983ad841b2Smrg 
5993ad841b2Smrg   /* We need a cgraph_node for it.  */
6003ad841b2Smrg   cgraph_node::get_create (fndecl);
6013ad841b2Smrg   /* Normally, cgraph_node::expand () would call
6023ad841b2Smrg      init_function_start (and a bunch of other stuff),
6033ad841b2Smrg      and invoke the expand pass, but it also runs
6043ad841b2Smrg      all of the other passes.  So just do the minimum
6053ad841b2Smrg      needed to get from gimple-SSA to RTL.  */
6063ad841b2Smrg   rtl_opt_pass *expand_pass = make_pass_expand (g);
6073ad841b2Smrg   push_cfun (fun);
6083ad841b2Smrg   init_function_start (fndecl);
6093ad841b2Smrg   expand_pass->execute (fun);
6103ad841b2Smrg   pop_cfun ();
6113ad841b2Smrg   delete expand_pass;
6123ad841b2Smrg 
6133ad841b2Smrg   /* On x86_64, I get this:
6143ad841b2Smrg        (note 3 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
6153ad841b2Smrg        (note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
6163ad841b2Smrg        (insn 5 2 6 2 (set (reg:SI 87 [ D.59 ])
6173ad841b2Smrg 			  (const_int 42 [0x2a])) -1 (nil))
6183ad841b2Smrg        (insn 6 5 10 2 (set (reg:SI 88 [ <retval> ])
6193ad841b2Smrg 			   (reg:SI 87 [ D.59 ])) -1 (nil))
6203ad841b2Smrg        (insn 10 6 11 2 (set (reg/i:SI 0 ax)
6213ad841b2Smrg 			    (reg:SI 88 [ <retval> ])) -1 (nil))
6223ad841b2Smrg        (insn 11 10 0 2 (use (reg/i:SI 0 ax)) -1 (nil))
6233ad841b2Smrg 
6243ad841b2Smrg      On cr16-elf I get this:
6253ad841b2Smrg        (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
6263ad841b2Smrg        (insn 2 4 3 2 (set (reg:SI 24)
6273ad841b2Smrg 	    (reg/f:SI 16 virtual-incoming-args)) -1
6283ad841b2Smrg 	  (nil))
6293ad841b2Smrg        (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG)
6303ad841b2Smrg        (insn 6 3 7 2 (set (reg:HI 22 [ _1 ])
6313ad841b2Smrg 	    (const_int 42 [0x2a])) -1
6323ad841b2Smrg 	 (nil))
6333ad841b2Smrg        (insn 7 6 11 2 (set (reg:HI 23 [ <retval> ])
6343ad841b2Smrg 	   (reg:HI 22 [ _1 ])) -1
6353ad841b2Smrg 	 (nil))
6363ad841b2Smrg        (insn 11 7 12 2 (set (reg/i:HI 0 r0)
6373ad841b2Smrg 	   (reg:HI 23 [ <retval> ])) -1
6383ad841b2Smrg 	 (nil))
6393ad841b2Smrg        (insn 12 11 0 2 (use (reg/i:HI 0 r0)) -1
6403ad841b2Smrg 	 (nil)).  */
6413ad841b2Smrg   verify_three_block_rtl_cfg (fun);
6423ad841b2Smrg 
6433ad841b2Smrg   /* Verify as much of the RTL as we can whilst avoiding
6443ad841b2Smrg      target-specific behavior.  */
6453ad841b2Smrg   basic_block bb2 = get_real_block (fun);
6463ad841b2Smrg 
6473ad841b2Smrg   /* Expect a NOTE_INSN_BASIC_BLOCK... */
6483ad841b2Smrg   rtx_insn *insn = BB_HEAD (bb2);
6493ad841b2Smrg   ASSERT_TRUE (insn != NULL);
6503ad841b2Smrg   ASSERT_EQ (NOTE, insn->code);
6513ad841b2Smrg   ASSERT_EQ (NOTE_INSN_BASIC_BLOCK, NOTE_KIND (insn));
6523ad841b2Smrg   ASSERT_EQ (bb2, NOTE_BASIC_BLOCK (insn));
6533ad841b2Smrg 
6543ad841b2Smrg   /* ...etc; any further checks are likely to over-specify things
6553ad841b2Smrg      and run us into target dependencies.  */
6563ad841b2Smrg 
6573ad841b2Smrg   /* Verify that print_rtl_function is sane.  */
6583ad841b2Smrg   named_temp_file tmp_out (".rtl");
6593ad841b2Smrg   FILE *outfile = fopen (tmp_out.get_filename (), "w");
6603ad841b2Smrg   print_rtx_function (outfile, fun, true);
6613ad841b2Smrg   fclose (outfile);
6623ad841b2Smrg 
6633ad841b2Smrg   char *dump = read_file (SELFTEST_LOCATION, tmp_out.get_filename ());
6643ad841b2Smrg   ASSERT_STR_CONTAINS (dump, "(function \"test_fn\"\n");
6653ad841b2Smrg   ASSERT_STR_CONTAINS (dump, "  (insn-chain\n");
6663ad841b2Smrg   ASSERT_STR_CONTAINS (dump, "    (block 2\n");
6673ad841b2Smrg   ASSERT_STR_CONTAINS (dump, "      (edge-from entry (flags \"FALLTHRU\"))\n");
6683ad841b2Smrg   ASSERT_STR_CONTAINS (dump, "      (cinsn "); /* ...etc.  */
6693ad841b2Smrg   ASSERT_STR_CONTAINS (dump, "      (edge-to exit (flags \"FALLTHRU\"))\n");
6703ad841b2Smrg   ASSERT_STR_CONTAINS (dump, "    ) ;; block 2\n");
6713ad841b2Smrg   ASSERT_STR_CONTAINS (dump, "  ) ;; insn-chain\n");
6723ad841b2Smrg   ASSERT_STR_CONTAINS (dump, "  (crtl\n");
6733ad841b2Smrg   ASSERT_STR_CONTAINS (dump, "  ) ;; crtl\n");
6743ad841b2Smrg   ASSERT_STR_CONTAINS (dump, ") ;; function \"test_fn\"\n");
6753ad841b2Smrg 
6763ad841b2Smrg   free (dump);
677cef8759bSmrg   free_after_compilation (fun);
6783ad841b2Smrg }
6793ad841b2Smrg 
6803ad841b2Smrg /* Run all of the selftests within this file.  */
6813ad841b2Smrg 
6823ad841b2Smrg void
function_tests_c_tests()6833ad841b2Smrg function_tests_c_tests ()
6843ad841b2Smrg {
6853ad841b2Smrg   test_fndecl_int_void ();
6863ad841b2Smrg   test_fndecl_float_intchar ();
6873ad841b2Smrg   test_gimplification ();
6883ad841b2Smrg   test_building_cfg ();
6893ad841b2Smrg   test_conversion_to_ssa ();
690*4c3eb207Smrg   test_ranges ();
6913ad841b2Smrg   test_expansion_to_rtl ();
6923ad841b2Smrg }
6933ad841b2Smrg 
6943ad841b2Smrg } // namespace selftest
6953ad841b2Smrg 
6963ad841b2Smrg #endif /* #if CHECKING_P */
697