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