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