d: Merge upstream dmd, druntime c8ae4adb2e, phobos 792c8b7c1.
[official-gcc.git] / gcc / value-range-storage.h
blob0cf95ebf7c127bf7bce9ffb4d966dc557efbcb9e
1 /* Support routines for vrange storage.
2 Copyright (C) 2022 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez <aldyh@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #ifndef GCC_VALUE_RANGE_STORAGE_H
22 #define GCC_VALUE_RANGE_STORAGE_H
24 // This class is used to allocate the minimum amount of storage needed
25 // for a given range. Storage is automatically freed at destruction
26 // of the class.
28 class vrange_allocator
30 public:
31 vrange_allocator () { }
32 virtual ~vrange_allocator () { }
33 // Allocate a range of TYPE.
34 vrange *alloc_vrange (tree type);
35 // Allocate a memory block of BYTES.
36 virtual void *alloc (unsigned bytes) = 0;
37 virtual void free (void *p) = 0;
38 // Return a clone of SRC.
39 template <typename T> T *clone (const T &src);
40 private:
41 irange *alloc_irange (unsigned pairs);
42 frange *alloc_frange ();
43 void operator= (const vrange_allocator &) = delete;
46 // This class is used to allocate chunks of memory that can store
47 // ranges as memory efficiently as possible. It is meant to be used
48 // when long term storage of a range is needed. The class can be used
49 // with any vrange_allocator (i.e. alloca or GC).
51 class vrange_storage
53 public:
54 vrange_storage (vrange_allocator *alloc) : m_alloc (alloc) { }
55 void *alloc_slot (const vrange &r);
56 void free (void *slot) { m_alloc->free (slot); }
57 void get_vrange (const void *slot, vrange &r, tree type);
58 void set_vrange (void *slot, const vrange &r);
59 static bool fits_p (const void *slot, const vrange &r);
60 private:
61 DISABLE_COPY_AND_ASSIGN (vrange_storage);
62 vrange_allocator *m_alloc;
65 // A chunk of memory pointing to an irange storage.
67 class GTY ((variable_size)) irange_storage_slot
69 public:
70 static irange_storage_slot *alloc_slot (vrange_allocator &, const irange &r);
71 void set_irange (const irange &r);
72 void get_irange (irange &r, tree type) const;
73 wide_int get_nonzero_bits () const { return m_ints[0]; }
74 bool fits_p (const irange &r) const;
75 static size_t size (const irange &r);
76 void dump () const;
77 private:
78 DISABLE_COPY_AND_ASSIGN (irange_storage_slot);
79 friend void gt_ggc_mx_irange_storage_slot (void *);
80 friend void gt_pch_p_19irange_storage_slot (void *, void *,
81 gt_pointer_operator, void *);
82 friend void gt_pch_nx_irange_storage_slot (void *);
84 // This is the maximum number of wide_int's allowed in the trailing
85 // ints structure, without going over 16 bytes (128 bits) in the
86 // control word that preceeds the HOST_WIDE_INTs in
87 // trailing_wide_ints::m_val[].
88 static const unsigned MAX_INTS = 12;
90 // Maximum number of range pairs we can handle, considering the
91 // nonzero bits take one wide_int.
92 static const unsigned MAX_PAIRS = (MAX_INTS - 1) / 2;
94 // Constructor is private to disallow stack initialization. Use
95 // alloc_slot() to create objects.
96 irange_storage_slot (const irange &r);
98 static unsigned num_wide_ints_needed (const irange &r);
100 trailing_wide_ints<MAX_INTS> m_ints;
103 // A chunk of memory to store an frange to long term memory.
105 class GTY (()) frange_storage_slot
107 public:
108 static frange_storage_slot *alloc_slot (vrange_allocator &, const frange &r);
109 void set_frange (const frange &r);
110 void get_frange (frange &r, tree type) const;
111 bool fits_p (const frange &) const;
112 private:
113 frange_storage_slot (const frange &r) { set_frange (r); }
114 DISABLE_COPY_AND_ASSIGN (frange_storage_slot);
116 enum value_range_kind m_kind;
117 REAL_VALUE_TYPE m_min;
118 REAL_VALUE_TYPE m_max;
119 bool m_pos_nan;
120 bool m_neg_nan;
123 class obstack_vrange_allocator final: public vrange_allocator
125 public:
126 obstack_vrange_allocator ()
128 obstack_init (&m_obstack);
130 virtual ~obstack_vrange_allocator () final override
132 obstack_free (&m_obstack, NULL);
134 virtual void *alloc (unsigned bytes) final override
136 return obstack_alloc (&m_obstack, bytes);
138 virtual void free (void *) final override { }
139 private:
140 obstack m_obstack;
143 class ggc_vrange_allocator final: public vrange_allocator
145 public:
146 ggc_vrange_allocator () { }
147 virtual ~ggc_vrange_allocator () final override { }
148 virtual void *alloc (unsigned bytes) final override
150 return ggc_internal_alloc (bytes);
152 virtual void free (void *p) final override
154 return ggc_free (p);
158 // Return a new range to hold ranges of TYPE. The newly allocated
159 // range is initialized to VR_UNDEFINED.
161 inline vrange *
162 vrange_allocator::alloc_vrange (tree type)
164 if (irange::supports_p (type))
165 return alloc_irange (2);
166 if (frange::supports_p (type))
167 return alloc_frange ();
168 return NULL;
169 gcc_unreachable ();
172 // Return a new range with NUM_PAIRS.
174 inline irange *
175 vrange_allocator::alloc_irange (unsigned num_pairs)
177 // Never allocate 0 pairs.
178 // Don't allocate 1 either, or we get legacy value_range's.
179 if (num_pairs < 2)
180 num_pairs = 2;
182 size_t nbytes = sizeof (tree) * 2 * num_pairs;
184 // Allocate the irange and required memory for the vector.
185 void *r = alloc (sizeof (irange));
186 tree *mem = static_cast <tree *> (alloc (nbytes));
187 return new (r) irange (mem, num_pairs);
190 inline frange *
191 vrange_allocator::alloc_frange ()
193 void *r = alloc (sizeof (frange));
194 return new (r) frange ();
197 // Return a clone of an irange.
199 template <>
200 inline irange *
201 vrange_allocator::clone <irange> (const irange &src)
203 irange *r = alloc_irange (src.num_pairs ());
204 *r = src;
205 return r;
208 // Return a clone of an frange.
210 template <>
211 inline frange *
212 vrange_allocator::clone <frange> (const frange &src)
214 frange *r = alloc_frange ();
215 *r = src;
216 return r;
219 // Return a clone of a vrange.
221 template <>
222 inline vrange *
223 vrange_allocator::clone <vrange> (const vrange &src)
225 if (is_a <irange> (src))
226 return clone <irange> (as_a <irange> (src));
227 if (is_a <frange> (src))
228 return clone <frange> (as_a <frange> (src));
229 return NULL;
230 gcc_unreachable ();
233 #endif // GCC_VALUE_RANGE_STORAGE_H