xref: /netbsd/external/gpl3/gcc/dist/gcc/ggc-tests.c (revision dd083157)
1 /* Unit tests for GCC's garbage collector (and gengtype etc).
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 "tree-core.h"
24 #include "tree.h"
25 #include "ggc-internal.h" /* (for ggc_force_collect).  */
26 #include "selftest.h"
27 
28 #if CHECKING_P
29 
30 /* A helper function for writing ggc tests.  */
31 
32 void
forcibly_ggc_collect()33 selftest::forcibly_ggc_collect ()
34 {
35   ggc_force_collect = true;
36   ggc_collect ();
37   ggc_force_collect = false;
38 }
39 
40 /* The various GTY markers must be outside of a namespace to be seen by
41    gengtype, so we don't put this file within the selftest namespace.  */
42 
43 
44 
45 /* Verify that a simple struct works, and that it can
46    own references to non-roots, and have them be marked.  */
47 
48 struct GTY(()) test_struct
49 {
50   struct test_struct *other;
51 };
52 
53 static GTY(()) test_struct *root_test_struct;
54 
55 static void
test_basic_struct()56 test_basic_struct ()
57 {
58   root_test_struct = ggc_cleared_alloc <test_struct> ();
59   root_test_struct->other = ggc_cleared_alloc <test_struct> ();
60 
61   selftest::forcibly_ggc_collect ();
62 
63   ASSERT_TRUE (ggc_marked_p (root_test_struct));
64   ASSERT_TRUE (ggc_marked_p (root_test_struct->other));
65 }
66 
67 
68 
69 /* Selftest for GTY((length)).  */
70 
71 /* A test struct using GTY((length)).  */
72 
73 struct GTY(()) test_of_length
74 {
75   int num_elem;
76   struct test_of_length * GTY ((length ("%h.num_elem"))) elem[1];
77 };
78 
79 static GTY(()) test_of_length *root_test_of_length;
80 
81 static void
test_length()82 test_length ()
83 {
84   const int count = 5;
85   size_t sz = sizeof (test_of_length) + (count- 1) * sizeof (test_of_length *);
86   root_test_of_length = (test_of_length *)ggc_internal_cleared_alloc (sz);
87   root_test_of_length->num_elem = count;
88   for (int i = 0; i < count; i++)
89     root_test_of_length->elem[i] = ggc_cleared_alloc <test_of_length> ();
90 
91   selftest::forcibly_ggc_collect ();
92 
93   ASSERT_TRUE (ggc_marked_p (root_test_of_length));
94   for (int i = 0; i < count; i++)
95     ASSERT_TRUE (ggc_marked_p (root_test_of_length->elem[i]));
96 }
97 
98 
99 
100 /* Selftest for unions, GTY((tag)), and GTY((desc)).  */
101 
102 /* A struct with a reference that's an a different offset to test_struct,
103    to ensure that we're using the correct types.  */
104 
105 struct GTY(()) test_other
106 {
107   char dummy[256];
108   test_struct *m_ptr;
109 };
110 
111 enum which_field
112 {
113   WHICH_FIELD_USE_TEST_STRUCT,
114   WHICH_FIELD_USE_TEST_OTHER
115 };
116 
117 /* An example function for use by a GTY((desc)) marker.  */
118 
119 static enum which_field
calc_desc(int kind)120 calc_desc (int kind)
121 {
122   switch (kind)
123     {
124     case 0: return WHICH_FIELD_USE_TEST_STRUCT;
125     case 1: return WHICH_FIELD_USE_TEST_OTHER;
126     default:
127       gcc_unreachable ();
128     }
129 }
130 
131 /* A struct containing an example of a union, showing the "tag" and
132    "desc" markers.  */
133 
134 struct GTY(()) test_of_union
135 {
136   int m_kind;
137   union u {
138     test_struct * GTY ((tag ("WHICH_FIELD_USE_TEST_STRUCT") )) u_test_struct;
139     test_other * GTY ((tag ("WHICH_FIELD_USE_TEST_OTHER") )) u_test_other;
140   } GTY ((desc ("calc_desc (%0.m_kind)"))) m_u;
141 };
142 
143 /* Example roots.  */
144 
145 static GTY(()) test_of_union *root_test_of_union_1;
146 static GTY(()) test_of_union *root_test_of_union_2;
147 
148 /* Verify that the above work correctly.  */
149 
150 static void
test_union()151 test_union ()
152 {
153   root_test_of_union_1 = ggc_cleared_alloc <test_of_union> ();
154   root_test_of_union_1->m_kind = 0;
155   test_struct *ts = ggc_cleared_alloc <test_struct> ();
156   root_test_of_union_1->m_u.u_test_struct = ts;
157 
158   root_test_of_union_2 = ggc_cleared_alloc <test_of_union> ();
159   root_test_of_union_2->m_kind = 1;
160   test_other *other = ggc_cleared_alloc <test_other> ();
161   root_test_of_union_2->m_u.u_test_other = other;
162   test_struct *referenced_by_other = ggc_cleared_alloc <test_struct> ();
163   other->m_ptr = referenced_by_other;
164 
165   selftest::forcibly_ggc_collect ();
166 
167   ASSERT_TRUE (ggc_marked_p (root_test_of_union_1));
168   ASSERT_TRUE (ggc_marked_p (ts));
169 
170   ASSERT_TRUE (ggc_marked_p (root_test_of_union_2));
171   ASSERT_TRUE (ggc_marked_p (other));
172   ASSERT_TRUE (ggc_marked_p (referenced_by_other));
173 }
174 
175 
176 
177 /* Verify that destructors get run when instances are collected.  */
178 
class()179 class GTY(()) test_struct_with_dtor
180 {
181 public:
182   /* This struct has a destructor; it *ought* to be called
183      by the ggc machinery when instances are collected.  */
184   ~test_struct_with_dtor () { dtor_call_count++; }
185 
186   static int dtor_call_count;
187 };
188 
189 int test_struct_with_dtor::dtor_call_count;
190 
191 static void
test_finalization()192 test_finalization ()
193 {
194 #if GCC_VERSION >= 4003
195   ASSERT_FALSE (need_finalization_p <test_struct> ());
196   ASSERT_TRUE (need_finalization_p <test_struct_with_dtor> ());
197 #endif
198 
199   /* Create some garbage.  */
200   const int count = 10;
201   for (int i = 0; i < count; i++)
202     ggc_cleared_alloc <test_struct_with_dtor> ();
203 
204   test_struct_with_dtor::dtor_call_count = 0;
205 
206   selftest::forcibly_ggc_collect ();
207 
208   /* Verify that the destructor was run for each instance.  */
209   ASSERT_EQ (count, test_struct_with_dtor::dtor_call_count);
210 }
211 
212 
213 
214 /* Verify that a global can be marked as "deletable".  */
215 
216 static GTY((deletable)) test_struct *test_of_deletable;
217 
218 static void
test_deletable_global()219 test_deletable_global ()
220 {
221   test_of_deletable = ggc_cleared_alloc <test_struct> ();
222   ASSERT_TRUE (test_of_deletable != NULL);
223 
224   selftest::forcibly_ggc_collect ();
225 
226   ASSERT_EQ (NULL, test_of_deletable);
227 }
228 
229 
230 
231 /* Verify that gengtype etc can cope with inheritance.  */
232 
233 class GTY((desc("%h.m_kind"), tag("0"))) example_base
234 {
235  public:
example_base()236   example_base ()
237     : m_kind (0),
238       m_a (ggc_cleared_alloc <test_struct> ())
239   {}
240 
241   void *
new(size_t sz)242   operator new (size_t sz)
243   {
244     return ggc_internal_cleared_alloc (sz);
245   }
246 
247  protected:
example_base(int kind)248   example_base (int kind)
249     : m_kind (kind),
250       m_a (ggc_cleared_alloc <test_struct> ())
251   {}
252 
253  public:
254   int m_kind;
255   test_struct *m_a;
256 };
257 
258 class GTY((tag("1"))) some_subclass : public example_base
259 {
260  public:
some_subclass()261   some_subclass ()
262     : example_base (1),
263       m_b (ggc_cleared_alloc <test_struct> ())
264   {}
265 
266   test_struct *m_b;
267 };
268 
269 class GTY((tag("2"))) some_other_subclass : public example_base
270 {
271  public:
some_other_subclass()272   some_other_subclass ()
273     : example_base (2),
274       m_c (ggc_cleared_alloc <test_struct> ())
275   {}
276 
277   test_struct *m_c;
278 };
279 
280 /* Various test roots, both expressed as a ptr to the actual class, and
281    as a ptr to the base class.  */
282 static GTY(()) example_base *test_example_base;
283 static GTY(()) some_subclass *test_some_subclass;
284 static GTY(()) some_other_subclass *test_some_other_subclass;
285 static GTY(()) example_base *test_some_subclass_as_base_ptr;
286 static GTY(()) example_base *test_some_other_subclass_as_base_ptr;
287 
288 static void
test_inheritance()289 test_inheritance ()
290 {
291   test_example_base = new example_base ();
292   test_some_subclass = new some_subclass ();
293   test_some_other_subclass = new some_other_subclass ();
294   test_some_subclass_as_base_ptr = new some_subclass ();
295   test_some_other_subclass_as_base_ptr = new some_other_subclass ();
296 
297   selftest::forcibly_ggc_collect ();
298 
299   /* Verify that the roots and everything referenced by them got marked
300      (both for fields in the base class and those in subclasses).  */
301   ASSERT_TRUE (ggc_marked_p (test_example_base));
302   ASSERT_TRUE (ggc_marked_p (test_example_base->m_a));
303 
304   ASSERT_TRUE (ggc_marked_p (test_some_subclass));
305   ASSERT_TRUE (ggc_marked_p (test_some_subclass->m_a));
306   ASSERT_TRUE (ggc_marked_p (test_some_subclass->m_b));
307 
308   ASSERT_TRUE (ggc_marked_p (test_some_other_subclass));
309   ASSERT_TRUE (ggc_marked_p (test_some_other_subclass->m_a));
310   ASSERT_TRUE (ggc_marked_p (test_some_other_subclass->m_c));
311 
312   ASSERT_TRUE (ggc_marked_p (test_some_subclass_as_base_ptr));
313   ASSERT_TRUE (ggc_marked_p (test_some_subclass_as_base_ptr->m_a));
314   ASSERT_TRUE (ggc_marked_p (((some_subclass *)
315 			      test_some_subclass_as_base_ptr)->m_b));
316 
317   ASSERT_TRUE (ggc_marked_p (test_some_other_subclass_as_base_ptr));
318   ASSERT_TRUE (ggc_marked_p (test_some_other_subclass_as_base_ptr->m_a));
319   ASSERT_TRUE (ggc_marked_p (((some_other_subclass *)
320 			      test_some_other_subclass_as_base_ptr)->m_c));
321 }
322 
323 
324 
325 /* Test of chain_next/chain_prev
326 
327    Construct a very long linked list, so that without
328    the chain_next/chain_prev optimization we'd have
329    a stack overflow when gt_ggc_mx_test_node recurses.  */
330 
331 struct GTY(( chain_next ("%h.m_next"),
332 	     chain_prev ("%h.m_prev") )) test_node
333 {
334   test_node *m_prev;
335   test_node *m_next;
336   int m_idx;
337 };
338 
339 static GTY(()) test_node *root_test_node;
340 
341 static void
test_chain_next()342 test_chain_next ()
343 {
344   /* Ideally we would construct a long list so that the number of
345      stack frames would be deep enough to crash if gengtype has created
346      something that recurses.
347 
348      However, as the list is lengthened to increase the chance of
349      overflowing the stack, the test will require more time and memory
350      to run.  On a Fedora 20 x86_64 box with 128GB of RAM, count=2000000
351      without the chain_next optimization reliably overflowed the stack,
352      but the test took 0.5s to run.
353 
354      For now this test runs with a low value for "count", which defeats
355      the main purpose of the test - though it at least gives us coverage
356      for walking a GTY((chain_next)) list.
357 
358      We could potentially increase this value once we have a better sense
359      of the time and space requirements of the test on different hosts,
360      or perhaps find a way to reduce the stack size when running this
361      testcase.  */
362   const int count = 10;
363 
364   /* Build the linked list.  */
365   root_test_node = ggc_cleared_alloc <test_node> ();
366   test_node *tail_node = root_test_node;
367   for (int i = 0; i < count; i++)
368     {
369       test_node *new_node = ggc_cleared_alloc <test_node> ();
370       tail_node->m_next = new_node;
371       new_node->m_prev = tail_node;
372       new_node->m_idx = i;
373       tail_node = new_node;
374     }
375 
376   selftest::forcibly_ggc_collect ();
377 
378   /* If we got here, we survived.  */
379 
380   /* Verify that all nodes in the list were marked.  */
381   ASSERT_TRUE (ggc_marked_p (root_test_node));
382   test_node *iter_node = root_test_node->m_next;
383   for (int i = 0; i < count; i++)
384     {
385       ASSERT_TRUE (ggc_marked_p (iter_node));
386       ASSERT_EQ (i, iter_node->m_idx);
387       iter_node = iter_node->m_next;
388     }
389 }
390 
391 
392 
393 /* Test for GTY((user)).  */
394 
395 struct GTY((user)) user_struct
396 {
397   char dummy[16];
398   test_struct *m_ptr;
399 };
400 
401 static GTY(()) user_struct *root_user_struct_ptr;
402 
403 /* A global for verifying that the user-provided gt_ggc_mx gets
404    called.  */
405 static int num_calls_to_user_gt_ggc_mx;
406 
407 /* User-provided implementation of gt_ggc_mx.  */
408 
409 static void
gt_ggc_mx(user_struct * p)410 gt_ggc_mx (user_struct *p)
411 {
412   num_calls_to_user_gt_ggc_mx++;
413   gt_ggc_mx_test_struct (p->m_ptr);
414 }
415 
416 /* User-provided implementation of gt_pch_nx.  */
417 
418 static void
gt_pch_nx(user_struct * p)419 gt_pch_nx (user_struct *p)
420 {
421   gt_pch_nx_test_struct (p->m_ptr);
422 }
423 
424 /* User-provided implementation of gt_pch_nx.  */
425 
426 static void
gt_pch_nx(user_struct * p,gt_pointer_operator op,void * cookie)427 gt_pch_nx (user_struct *p, gt_pointer_operator op, void *cookie)
428 {
429   op (&(p->m_ptr), cookie);
430 }
431 
432 /* Verify that GTY((user)) works.  */
433 
434 static void
test_user_struct()435 test_user_struct ()
436 {
437   root_user_struct_ptr = ggc_cleared_alloc <user_struct> ();
438   test_struct *referenced = ggc_cleared_alloc <test_struct> ();
439   root_user_struct_ptr->m_ptr = referenced;
440 
441   num_calls_to_user_gt_ggc_mx = 0;
442 
443   selftest::forcibly_ggc_collect ();
444 
445   ASSERT_TRUE (ggc_marked_p (root_user_struct_ptr));
446   ASSERT_TRUE (ggc_marked_p (referenced));
447   ASSERT_TRUE (num_calls_to_user_gt_ggc_mx > 0);
448 }
449 
450 
451 
452 /* Smoketest to ensure that the tree type is marked.  */
453 
454 static GTY(()) tree dummy_unittesting_tree;
455 
456 static void
test_tree_marking()457 test_tree_marking ()
458 {
459   dummy_unittesting_tree = build_int_cst (integer_type_node, 1066);
460 
461   selftest::forcibly_ggc_collect ();
462 
463   ASSERT_TRUE (ggc_marked_p (dummy_unittesting_tree));
464 }
465 
466 
467 
468 /* Ideas for other tests:
469    - pch-handling  */
470 
471 namespace selftest {
472 
473 /* Run all of the selftests within this file.  */
474 
475 void
ggc_tests_c_tests()476 ggc_tests_c_tests ()
477 {
478   test_basic_struct ();
479   test_length ();
480   test_union ();
481   test_finalization ();
482   test_deletable_global ();
483   test_inheritance ();
484   test_chain_next ();
485   test_user_struct ();
486   test_tree_marking ();
487 }
488 
489 } // namespace selftest
490 
491 #include "gt-ggc-tests.h"
492 
493 #else /* #if CHECKING_P */
494 
495 /* The #if CHECKING_P code above has various GTY-marked roots.
496    gengtype has no knowledge of the preprocessor, and so detects
497    these roots and writes them out to gt-ggc-tests.h.
498    In a !CHECKING_P build we can ignore gt-ggc-tests.h, but the
499    root tables are referenced in the various generated gtype-*.c
500    files like this:
501 
502       ...snip...
503       extern const struct ggc_root_tab gt_ggc_r_gt_ggc_tests_h[];
504       ...snip...
505 
506       EXPORTED_CONST struct ggc_root_tab * const gt_ggc_rtab[] = {
507         ...snip...
508         gt_ggc_r_gt_ggc_tests_h,
509         ...snip...
510       };
511 
512     Hence to avoid a link failure, we provide dummy implementations
513     of these root tables in an unchecked build.
514 
515     Note that these conditional roots imply that PCH files are
516     incompatible between checked and unchecked builds.  */
517 
518 EXPORTED_CONST struct ggc_root_tab gt_ggc_r_gt_ggc_tests_h[] = {
519   LAST_GGC_ROOT_TAB
520 };
521 
522 EXPORTED_CONST struct ggc_root_tab gt_ggc_rd_gt_ggc_tests_h[] = {
523   LAST_GGC_ROOT_TAB
524 };
525 
526 #endif /* #else clause of #if CHECKING_P */
527