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