1 /* Unit tests for function-handling.
2    Copyright (C) 2015-2020 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "opts.h"
25 #include "hash-set.h"
26 #include "fixed-value.h"
27 #include "alias.h"
28 #include "flags.h"
29 #include "symtab.h"
30 #include "tree-core.h"
31 #include "stor-layout.h"
32 #include "tree.h"
33 #include "stringpool.h"
34 #include "stor-layout.h"
35 #include "rtl.h"
36 #include "predict.h"
37 #include "vec.h"
38 #include "hashtab.h"
39 #include "hash-set.h"
40 #include "hard-reg-set.h"
41 #include "input.h"
42 #include "function.h"
43 #include "dominance.h"
44 #include "cfg.h"
45 #include "cfganal.h"
46 #include "basic-block.h"
47 #include "tree-ssa-alias.h"
48 #include "internal-fn.h"
49 #include "gimple-fold.h"
50 #include "gimple-expr.h"
51 #include "toplev.h"
52 #include "print-tree.h"
53 #include "tree-iterator.h"
54 #include "gimplify.h"
55 #include "tree-cfg.h"
56 #include "basic-block.h"
57 #include "alias.h"
58 #include "symtab.h"
59 #include "inchash.h"
60 #include "tree.h"
61 #include "fold-const.h"
62 #include "stor-layout.h"
63 #include "stmt.h"
64 #include "hash-table.h"
65 #include "tree-ssa-alias.h"
66 #include "internal-fn.h"
67 #include "gimple-expr.h"
68 #include "is-a.h"
69 #include "gimple.h"
70 #include "tree-pass.h"
71 #include "context.h"
72 #include "hash-map.h"
73 #include "plugin-api.h"
74 #include "ipa-ref.h"
75 #include "cgraph.h"
76 #include "selftest.h"
77 #include "print-rtl.h"
78 
79 #if CHECKING_P
80 
81 namespace selftest {
82 
83 /* Helper function for selftests of function-creation.  */
84 
85 tree
make_fndecl(tree return_type,const char * name,vec<tree> & param_types,bool is_variadic)86 make_fndecl (tree return_type,
87 	     const char *name,
88 	     vec <tree> &param_types,
89 	     bool is_variadic)
90 {
91   tree fn_type;
92   if (is_variadic)
93     fn_type = build_varargs_function_type_array (return_type,
94 						 param_types.length (),
95 						 param_types.address ());
96   else
97     fn_type = build_function_type_array (return_type,
98 					 param_types.length (),
99 					 param_types.address ());
100   /* FIXME: this uses input_location: */
101   tree fndecl = build_fn_decl (name, fn_type);
102 
103   return fndecl;
104 }
105 
106 /* Verify creating a function declaration equivalent to the following
107      int test_fndecl_int_void (void);
108    C declaration.  */
109 
110 static void
test_fndecl_int_void()111 test_fndecl_int_void ()
112 {
113   auto_vec <tree> param_types;
114   const char *name = "test_fndecl_int_void";
115   tree fndecl = make_fndecl (integer_type_node,
116 			     name,
117 			     param_types);
118   ASSERT_TRUE (fndecl != NULL);
119 
120   /* Verify name of decl.  */
121   tree declname = DECL_NAME (fndecl);
122   ASSERT_TRUE (declname != NULL);
123   ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (declname));
124   /* We expect it to use a *copy* of the string we passed in.  */
125   const char *identifier_ptr = IDENTIFIER_POINTER (declname);
126   ASSERT_NE (name, identifier_ptr);
127   ASSERT_EQ (0, strcmp ("test_fndecl_int_void", identifier_ptr));
128 
129   /* Verify type of fndecl.  */
130   ASSERT_EQ (FUNCTION_DECL, TREE_CODE (fndecl));
131   tree fntype = TREE_TYPE (fndecl);
132   ASSERT_EQ (FUNCTION_TYPE, TREE_CODE (fntype));
133 
134   /* Verify return type.  */
135   ASSERT_EQ (integer_type_node, TREE_TYPE (fntype));
136 
137   /* Verify "void" args.  */
138   tree argtypes = TYPE_ARG_TYPES (fntype);
139   ASSERT_EQ (TREE_LIST, TREE_CODE (argtypes));
140   ASSERT_EQ (void_type_node, TREE_VALUE (argtypes));
141   ASSERT_EQ (NULL, TREE_CHAIN (argtypes));
142 }
143 
144 /* Verify creating a function declaration equivalent to the following
145      float test_fndecl_float_intchar (int, char);
146    C declaration.  */
147 
148 static void
test_fndecl_float_intchar()149 test_fndecl_float_intchar ()
150 {
151   auto_vec <tree> param_types;
152   param_types.safe_push (integer_type_node);
153   param_types.safe_push (char_type_node);
154   const char *name = "test_fndecl_float_intchar";
155   tree fndecl = make_fndecl (float_type_node,
156 			     name,
157 			     param_types);
158   ASSERT_TRUE (fndecl != NULL);
159 
160   /* Verify name of decl.  */
161   tree declname = DECL_NAME (fndecl);
162   ASSERT_TRUE (declname != NULL);
163   ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (declname));
164   /* We expect it to use a *copy* of the string we passed in.  */
165   const char *identifier_ptr = IDENTIFIER_POINTER (declname);
166   ASSERT_NE (name, identifier_ptr);
167   ASSERT_EQ (0, strcmp (name, identifier_ptr));
168 
169   /* Verify type of fndecl.  */
170   ASSERT_EQ (FUNCTION_DECL, TREE_CODE (fndecl));
171   tree fntype = TREE_TYPE (fndecl);
172   ASSERT_EQ (FUNCTION_TYPE, TREE_CODE (fntype));
173 
174   /* Verify return type.  */
175   ASSERT_EQ (float_type_node, TREE_TYPE (fntype));
176 
177   /* Verify "(int, char)" args.  */
178   tree arg0 = TYPE_ARG_TYPES (fntype);
179   ASSERT_EQ (TREE_LIST, TREE_CODE (arg0));
180   ASSERT_EQ (integer_type_node, TREE_VALUE (arg0));
181   tree arg1 = TREE_CHAIN (arg0);
182   ASSERT_TRUE (arg1 != NULL);
183   ASSERT_EQ (TREE_LIST, TREE_CODE (arg1));
184   ASSERT_EQ (char_type_node, TREE_VALUE (arg1));
185   tree argterm = TREE_CHAIN (arg1);
186   ASSERT_TRUE (argterm != NULL);
187   ASSERT_EQ (TREE_LIST, TREE_CODE (argterm));
188   ASSERT_EQ (void_type_node, TREE_VALUE (argterm));
189   ASSERT_EQ (NULL, TREE_CHAIN (argterm));
190 }
191 
192 /* The test cases using these helper functions take a trivial function:
193 
194      int test_fn (void) { return 42; }
195 
196    and test various conversions done to it:
197 
198    - gimplification
199    - construction of the CFG
200    - conversion to SSA form
201    - expansion to RTL form
202 
203    In avoid having one overlong test case, this is broken
204    up into separate test cases for each stage, with helper functions
205    to minimize code duplication.
206 
207    Another approach would be to attempt to directly construct a function
208    in the appropriate representation at each stage, though presumably
209    that would exhibit different kinds of failure compared to this
210    approach.  */
211 
212 /* Construct this function:
213    int test_fn (void) { return 42; }
214    in generic tree form.  Return the fndecl.  */
215 
216 static tree
build_trivial_generic_function()217 build_trivial_generic_function ()
218 {
219   auto_vec <tree> param_types;
220   tree fndecl = make_fndecl (integer_type_node,
221 			     "test_fn",
222 			     param_types);
223   ASSERT_TRUE (fndecl != NULL);
224 
225   /* Populate the function.  */
226   tree retval = build_decl (UNKNOWN_LOCATION, RESULT_DECL,
227 			    NULL_TREE, integer_type_node);
228   DECL_ARTIFICIAL (retval) = 1;
229   DECL_IGNORED_P (retval) = 1;
230   DECL_RESULT (fndecl) = retval;
231 
232   /* Create a BIND_EXPR, and within it, a statement list.  */
233   tree stmt_list = alloc_stmt_list ();
234   tree_stmt_iterator stmt_iter = tsi_start (stmt_list);
235   tree block = make_node (BLOCK);
236   tree bind_expr
237     = build3 (BIND_EXPR, void_type_node, NULL, stmt_list, block);
238 
239   tree modify_retval = build2 (MODIFY_EXPR,
240 			       integer_type_node,
241 			       retval,
242 			       build_int_cst (integer_type_node, 42));
243   tree return_stmt = build1 (RETURN_EXPR,
244 			     integer_type_node,
245 			     modify_retval);
246   tsi_link_after (&stmt_iter, return_stmt, TSI_CONTINUE_LINKING);
247 
248   DECL_INITIAL (fndecl) = block;
249   BLOCK_SUPERCONTEXT (block) = fndecl;
250 
251   /* how to add to function? the following appears to be how to
252      set the body of a fndecl: */
253   DECL_SAVED_TREE(fndecl) = bind_expr;
254 
255   /* Ensure that locals appear in the debuginfo.  */
256   BLOCK_VARS (block) = BIND_EXPR_VARS (bind_expr);
257 
258   return fndecl;
259 }
260 
261 /* Construct this function:
262      int test_fn (void) { return 42; }
263    in "high gimple" form.  Return the fndecl.  */
264 
265 static tree
build_trivial_high_gimple_function()266 build_trivial_high_gimple_function ()
267 {
268   /* Construct a trivial function, and gimplify it: */
269   tree fndecl = build_trivial_generic_function ();
270   gimplify_function_tree (fndecl);
271   return fndecl;
272 }
273 
274 /* Build a CFG for a function in gimple form.  */
275 
276 static void
build_cfg(tree fndecl)277 build_cfg (tree fndecl)
278 {
279   function *fun = DECL_STRUCT_FUNCTION (fndecl);
280   ASSERT_TRUE (fun != NULL);
281   ASSERT_EQ (fndecl, fun->decl);
282 
283   /* We first have to lower control flow; for our trivial test function
284      this gives us:
285 	 test_fn ()
286 	 {
287 	   D.56 = 42;
288 	   goto <D.57>;
289 	   <D.57>:
290 	   return D.56;
291 	 }
292   */
293   gimple_opt_pass *lower_cf_pass = make_pass_lower_cf (g);
294   push_cfun (fun);
295   lower_cf_pass->execute (fun);
296   pop_cfun ();
297   delete lower_cf_pass;
298 
299   /* We can now convert to CFG form; for our trivial test function this
300      gives us:
301 	 test_fn ()
302 	 {
303 	   <bb 2>:
304 	   D.56 = 42;
305 	   return D.56;
306 	 }
307   */
308   gimple_opt_pass *build_cfg_pass = make_pass_build_cfg (g);
309   push_cfun (fun);
310   build_cfg_pass->execute (fun);
311   pop_cfun ();
312   delete build_cfg_pass;
313 }
314 
315 /* Convert a gimple+CFG function to SSA form.  */
316 
317 static void
convert_to_ssa(tree fndecl)318 convert_to_ssa (tree fndecl)
319 {
320   function *fun = DECL_STRUCT_FUNCTION (fndecl);
321   ASSERT_TRUE (fun != NULL);
322   ASSERT_EQ (fndecl, fun->decl);
323 
324   gimple_opt_pass *build_ssa_pass = make_pass_build_ssa (g);
325   push_cfun (fun);
326   build_ssa_pass->execute (fun);
327   pop_cfun ();
328   delete build_ssa_pass;
329 }
330 
331 /* Assuming we have a simple 3-block CFG like this:
332      [ENTRY] -> [block2] -> [EXIT]
333    get the "real" basic block (block 2).  */
334 
335 static basic_block
get_real_block(function * fun)336 get_real_block (function *fun)
337 {
338   ASSERT_TRUE (fun->cfg != NULL);
339   ASSERT_EQ (3, n_basic_blocks_for_fn (fun));
340   basic_block bb2 = (*fun->cfg->x_basic_block_info)[2];
341   ASSERT_TRUE (bb2 != NULL);
342   return bb2;
343 }
344 
345 /* Verify that we have a simple 3-block CFG: the two "fake" ones, and
346    a "real" one:
347      [ENTRY] -> [block2] -> [EXIT].  */
348 
349 static void
verify_three_block_cfg(function * fun)350 verify_three_block_cfg (function *fun)
351 {
352   ASSERT_TRUE (fun->cfg != NULL);
353   ASSERT_EQ (3, n_basic_blocks_for_fn (fun));
354   ASSERT_EQ (2, n_edges_for_fn (fun));
355 
356   /* The "fake" basic blocks.  */
357   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
358   ASSERT_TRUE (entry != NULL);
359   ASSERT_EQ (ENTRY_BLOCK, entry->index);
360 
361   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
362   ASSERT_TRUE (exit != NULL);
363   ASSERT_EQ (EXIT_BLOCK, exit->index);
364 
365   /* The "real" basic block.  */
366   basic_block bb2 = get_real_block (fun);
367   ASSERT_TRUE (bb2 != NULL);
368   ASSERT_EQ (2, bb2->index);
369 
370   /* Verify connectivity.  */
371   ASSERT_EQ (NULL, entry->preds);
372   ASSERT_EQ (1, entry->succs->length ());
373 
374   edge from_entry_to_bb2 = (*entry->succs)[0];
375   ASSERT_EQ (entry, from_entry_to_bb2->src);
376   ASSERT_EQ (bb2, from_entry_to_bb2->dest);
377 
378   ASSERT_EQ (1, bb2->preds->length ());
379   ASSERT_EQ (from_entry_to_bb2, (*bb2->preds)[0]);
380   ASSERT_EQ (1, bb2->succs->length ());
381 
382   edge from_bb2_to_exit = (*bb2->succs)[0];
383   ASSERT_EQ (bb2, from_bb2_to_exit->src);
384   ASSERT_EQ (exit, from_bb2_to_exit->dest);
385 
386   ASSERT_EQ (1, exit->preds->length ());
387   ASSERT_EQ (from_bb2_to_exit, (*exit->preds)[0]);
388   ASSERT_EQ (NULL, exit->succs);
389 }
390 
391 /* As above, but additionally verify the gimple statements are sane.  */
392 
393 static void
verify_three_block_gimple_cfg(function * fun)394 verify_three_block_gimple_cfg (function *fun)
395 {
396   verify_three_block_cfg (fun);
397 
398   /* The "fake" basic blocks should be flagged as gimple, but with have no
399      statements.  */
400   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
401   ASSERT_TRUE (entry != NULL);
402   ASSERT_EQ (0, entry->flags & BB_RTL);
403   ASSERT_EQ (NULL, bb_seq (entry));
404 
405   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
406   ASSERT_TRUE (exit != NULL);
407   ASSERT_EQ (0, entry->flags & BB_RTL);
408   ASSERT_EQ (NULL, bb_seq (exit));
409 
410   /* The "real" basic block should be flagged as gimple, and have one
411      or more statements.  */
412   basic_block bb2 = get_real_block (fun);
413   ASSERT_TRUE (bb2 != NULL);
414   ASSERT_EQ (0, entry->flags & BB_RTL);
415   ASSERT_TRUE (bb_seq (bb2) != NULL);
416 }
417 
418 /* As above, but additionally verify the RTL insns are sane.  */
419 
420 void
verify_three_block_rtl_cfg(function * fun)421 verify_three_block_rtl_cfg (function *fun)
422 {
423   verify_three_block_cfg (fun);
424 
425   /* The "fake" basic blocks should be flagged as RTL, but with no
426      insns.  */
427   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
428   ASSERT_TRUE (entry != NULL);
429   ASSERT_EQ (BB_RTL, entry->flags & BB_RTL);
430   ASSERT_EQ (NULL, BB_HEAD (entry));
431 
432   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
433   ASSERT_TRUE (exit != NULL);
434   ASSERT_EQ (BB_RTL, exit->flags & BB_RTL);
435   ASSERT_EQ (NULL, BB_HEAD (exit));
436 
437   /* The "real" basic block should be flagged as RTL, and have one
438      or more insns.  */
439   basic_block bb2 = get_real_block (fun);
440   ASSERT_TRUE (bb2 != NULL);
441   ASSERT_EQ (BB_RTL, bb2->flags & BB_RTL);
442   ASSERT_TRUE (BB_HEAD (bb2) != NULL);
443 }
444 
445 /* Test converting our trivial function:
446      int test_fn (void) { return 42; }
447    to gimple form.  */
448 
449 static void
test_gimplification()450 test_gimplification ()
451 {
452   tree fndecl = build_trivial_generic_function ();
453 
454   /* Convert to gimple: */
455   gimplify_function_tree (fndecl);
456 
457   /* Verify that we got gimple out of it.  */
458 
459   /* The function is now in GIMPLE form but the CFG has not been
460      built yet.  */
461 
462   /* We should have a struct function for the decl.  */
463   function *fun = DECL_STRUCT_FUNCTION (fndecl);
464   ASSERT_TRUE (fun != NULL);
465   ASSERT_EQ (fndecl, fun->decl);
466 
467   /* We expect a GIMPLE_BIND, with two gimple statements within it:
468        tmp = 42;
469        return tmp;  */
470 
471   gimple_seq seq_fn_body = gimple_body (fndecl);
472   ASSERT_TRUE (seq_fn_body != NULL);
473   gimple *bind_stmt = gimple_seq_first_stmt (seq_fn_body);
474   ASSERT_EQ (GIMPLE_BIND, gimple_code (bind_stmt));
475   ASSERT_EQ (NULL, bind_stmt->next);
476 
477   gimple_seq seq_bind_body = gimple_bind_body (as_a <gbind *> (bind_stmt));
478 
479   /* Verify that we have the 2 statements we expect.  */
480   ASSERT_TRUE (seq_bind_body != NULL);
481   gimple *stmt1 = gimple_seq_first_stmt (seq_bind_body);
482   ASSERT_TRUE (stmt1 != NULL);
483   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt1));
484   gimple *stmt2 = stmt1->next;
485   ASSERT_TRUE (stmt2 != NULL);
486   ASSERT_EQ (stmt1, stmt2->prev);
487   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt2));
488 }
489 
490 /* Test of building a CFG for a function in high gimple form.  */
491 
492 static void
test_building_cfg()493 test_building_cfg ()
494 {
495   /* Construct a trivial function, and gimplify it: */
496   tree fndecl = build_trivial_high_gimple_function ();
497   function *fun = DECL_STRUCT_FUNCTION (fndecl);
498   ASSERT_TRUE (fun != NULL);
499 
500   /* Build a CFG.  */
501   build_cfg (fndecl);
502 
503   /* The CFG-building code constructs a 4-block cfg (with
504      ENTRY and EXIT):
505        test_fn ()
506        {
507          <bb 2>:
508 	 D.65 = 42;
509 
510 	 <bb 3>:
511 	 return D.65;
512        }
513      and then ought to merge blocks 2 and 3 in cleanup_tree_cfg.
514 
515      Hence we should end up with a simple 3-block cfg, the two "fake" ones,
516      and a "real" one:
517        [ENTRY] -> [block2] -> [EXIT]
518      with code like this:
519 	 test_fn ()
520 	 {
521 	   <bb 2>:
522 	   D.56 = 42;
523 	   return D.56;
524 	 }
525   */
526   verify_three_block_gimple_cfg (fun);
527 
528   /* Verify the statements within the "real" block.  */
529   basic_block bb2 = get_real_block (fun);
530   gimple *stmt_a = gimple_seq_first_stmt (bb_seq (bb2));
531   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt_a));
532   gimple *stmt_b = stmt_a->next;
533   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt_b));
534   ASSERT_EQ (NULL, stmt_b->next);
535 }
536 
537 /* Test of conversion of gimple to SSA form.  */
538 
539 static void
test_conversion_to_ssa()540 test_conversion_to_ssa ()
541 {
542   /* As above, construct a trivial function, gimplify it, and build a CFG: */
543   tree fndecl = build_trivial_high_gimple_function ();
544   function *fun = DECL_STRUCT_FUNCTION (fndecl);
545   ASSERT_TRUE (fun != NULL);
546   build_cfg (fndecl);
547 
548   convert_to_ssa (fndecl);
549 
550   verify_three_block_gimple_cfg (fun);
551 
552   /* For out trivial test function we should now have something like
553      this:
554        test_fn ()
555        {
556 	 <bb 2>:
557 	 _1 = 42;
558 	 return _1;
559        }
560   */
561   basic_block bb2 = get_real_block (fun);
562   gimple *stmt_a = gimple_seq_first_stmt (bb_seq (bb2));
563   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt_a));
564 
565   gimple *stmt_b = stmt_a->next;
566   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt_b));
567   ASSERT_EQ (NULL, stmt_b->next);
568 
569   greturn *return_stmt = as_a <greturn *> (stmt_b);
570   ASSERT_EQ (SSA_NAME, TREE_CODE (gimple_return_retval (return_stmt)));
571 }
572 
573 /* Test range folding.  We must start this here because we need cfun
574    set.  */
575 
576 static void
test_ranges()577 test_ranges ()
578 {
579   tree fndecl = build_trivial_high_gimple_function ();
580   function *fun = DECL_STRUCT_FUNCTION (fndecl);
581   push_cfun (fun);
582   range_tests ();
583   pop_cfun ();
584 }
585 
586 /* Test of expansion from gimple-ssa to RTL.  */
587 
588 static void
test_expansion_to_rtl()589 test_expansion_to_rtl ()
590 {
591   /* As above, construct a trivial function, gimplify it, build a CFG,
592      and convert to SSA: */
593   tree fndecl = build_trivial_high_gimple_function ();
594   function *fun = DECL_STRUCT_FUNCTION (fndecl);
595   ASSERT_TRUE (fun != NULL);
596   build_cfg (fndecl);
597   convert_to_ssa (fndecl);
598 
599   /* We need a cgraph_node for it.  */
600   cgraph_node::get_create (fndecl);
601   /* Normally, cgraph_node::expand () would call
602      init_function_start (and a bunch of other stuff),
603      and invoke the expand pass, but it also runs
604      all of the other passes.  So just do the minimum
605      needed to get from gimple-SSA to RTL.  */
606   rtl_opt_pass *expand_pass = make_pass_expand (g);
607   push_cfun (fun);
608   init_function_start (fndecl);
609   expand_pass->execute (fun);
610   pop_cfun ();
611   delete expand_pass;
612 
613   /* On x86_64, I get this:
614        (note 3 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
615        (note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
616        (insn 5 2 6 2 (set (reg:SI 87 [ D.59 ])
617 			  (const_int 42 [0x2a])) -1 (nil))
618        (insn 6 5 10 2 (set (reg:SI 88 [ <retval> ])
619 			   (reg:SI 87 [ D.59 ])) -1 (nil))
620        (insn 10 6 11 2 (set (reg/i:SI 0 ax)
621 			    (reg:SI 88 [ <retval> ])) -1 (nil))
622        (insn 11 10 0 2 (use (reg/i:SI 0 ax)) -1 (nil))
623 
624      On cr16-elf I get this:
625        (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
626        (insn 2 4 3 2 (set (reg:SI 24)
627 	    (reg/f:SI 16 virtual-incoming-args)) -1
628 	  (nil))
629        (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG)
630        (insn 6 3 7 2 (set (reg:HI 22 [ _1 ])
631 	    (const_int 42 [0x2a])) -1
632 	 (nil))
633        (insn 7 6 11 2 (set (reg:HI 23 [ <retval> ])
634 	   (reg:HI 22 [ _1 ])) -1
635 	 (nil))
636        (insn 11 7 12 2 (set (reg/i:HI 0 r0)
637 	   (reg:HI 23 [ <retval> ])) -1
638 	 (nil))
639        (insn 12 11 0 2 (use (reg/i:HI 0 r0)) -1
640 	 (nil)).  */
641   verify_three_block_rtl_cfg (fun);
642 
643   /* Verify as much of the RTL as we can whilst avoiding
644      target-specific behavior.  */
645   basic_block bb2 = get_real_block (fun);
646 
647   /* Expect a NOTE_INSN_BASIC_BLOCK... */
648   rtx_insn *insn = BB_HEAD (bb2);
649   ASSERT_TRUE (insn != NULL);
650   ASSERT_EQ (NOTE, insn->code);
651   ASSERT_EQ (NOTE_INSN_BASIC_BLOCK, NOTE_KIND (insn));
652   ASSERT_EQ (bb2, NOTE_BASIC_BLOCK (insn));
653 
654   /* ...etc; any further checks are likely to over-specify things
655      and run us into target dependencies.  */
656 
657   /* Verify that print_rtl_function is sane.  */
658   named_temp_file tmp_out (".rtl");
659   FILE *outfile = fopen (tmp_out.get_filename (), "w");
660   print_rtx_function (outfile, fun, true);
661   fclose (outfile);
662 
663   char *dump = read_file (SELFTEST_LOCATION, tmp_out.get_filename ());
664   ASSERT_STR_CONTAINS (dump, "(function \"test_fn\"\n");
665   ASSERT_STR_CONTAINS (dump, "  (insn-chain\n");
666   ASSERT_STR_CONTAINS (dump, "    (block 2\n");
667   ASSERT_STR_CONTAINS (dump, "      (edge-from entry (flags \"FALLTHRU\"))\n");
668   ASSERT_STR_CONTAINS (dump, "      (cinsn "); /* ...etc.  */
669   ASSERT_STR_CONTAINS (dump, "      (edge-to exit (flags \"FALLTHRU\"))\n");
670   ASSERT_STR_CONTAINS (dump, "    ) ;; block 2\n");
671   ASSERT_STR_CONTAINS (dump, "  ) ;; insn-chain\n");
672   ASSERT_STR_CONTAINS (dump, "  (crtl\n");
673   ASSERT_STR_CONTAINS (dump, "  ) ;; crtl\n");
674   ASSERT_STR_CONTAINS (dump, ") ;; function \"test_fn\"\n");
675 
676   free (dump);
677   free_after_compilation (fun);
678 }
679 
680 /* Run all of the selftests within this file.  */
681 
682 void
function_tests_c_tests()683 function_tests_c_tests ()
684 {
685   test_fndecl_int_void ();
686   test_fndecl_float_intchar ();
687   test_gimplification ();
688   test_building_cfg ();
689   test_conversion_to_ssa ();
690   test_ranges ();
691   test_expansion_to_rtl ();
692 }
693 
694 } // namespace selftest
695 
696 #endif /* #if CHECKING_P */
697