aboutsummaryrefslogtreecommitdiff
path: root/gcc/value-range-storage.h
blob: dd6813873eaac58ae36bd176f90c7bc7714499eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* Support routines for vrange storage.
   Copyright (C) 2022-2024 Free Software Foundation, Inc.
   Contributed by Aldy Hernandez <aldyh@redhat.com>.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#ifndef GCC_VALUE_RANGE_STORAGE_H
#define GCC_VALUE_RANGE_STORAGE_H

// This class is used to allocate chunks of memory that can store
// ranges as memory efficiently as possible.

class vrange_allocator
{
public:
  // Use GC memory when GC is true, otherwise use obstacks.
  vrange_allocator (bool gc = false);
  ~vrange_allocator ();
  class vrange_storage *clone (const vrange &r);
  vrange_storage *clone_varying (tree type);
  vrange_storage *clone_undefined (tree type);
  void *alloc (size_t size);
  void free (void *);
private:
  DISABLE_COPY_AND_ASSIGN (vrange_allocator);
  class vrange_internal_alloc *m_alloc;
};

// Efficient memory storage for a vrange.
//
// The GTY marker here does nothing but get gengtype to generate the
// ggc_test_and_set_mark calls.  We ignore the derived classes, since
// they don't contain any pointers.

class GTY(()) vrange_storage
{
public:
  static vrange_storage *alloc (vrange_internal_alloc &, const vrange &);
  void get_vrange (vrange &r, tree type) const;
  void set_vrange (const vrange &r);
  bool fits_p (const vrange &r) const;
  bool equal_p (const vrange &r) const;
protected:
  // Stack initialization disallowed.
  vrange_storage () { }
};

// Efficient memory storage for an irange.

class irange_storage : public vrange_storage
{
public:
  static irange_storage *alloc (vrange_internal_alloc &, const irange &);
  void set_irange (const irange &r);
  void get_irange (irange &r, tree type) const;
  bool equal_p (const irange &r) const;
  bool fits_p (const irange &r) const;
  void dump () const;
private:
  DISABLE_COPY_AND_ASSIGN (irange_storage);
  static size_t size (const irange &r);
  const unsigned short *lengths_address () const;
  unsigned short *write_lengths_address ();

  // The shared precision of each number.
  unsigned short m_precision;

  // The max number of sub-ranges that fit in this storage.
  const unsigned char m_max_ranges;

  // The number of stored sub-ranges.
  unsigned char m_num_ranges;

  enum value_range_kind m_kind : 3;

  // The length of this is m_num_ranges * 2 + 2 to accomodate the bitmask.
  HOST_WIDE_INT m_val[1];

  // Another variable-length part of the structure following the HWIs.
  // This is the length of each wide_int in m_val.
  //
  // unsigned short m_len[];

  irange_storage (const irange &r);
};

// Efficient memory storage for a prange.

class prange_storage : public vrange_storage
{
public:
  static prange_storage *alloc (vrange_internal_alloc &, const prange &);
  void set_prange (const prange &r);
  void get_prange (prange &r, tree type) const;
  bool equal_p (const prange &r) const;
  bool fits_p (const prange &r) const;
  void dump () const;
private:
  DISABLE_COPY_AND_ASSIGN (prange_storage);
  prange_storage (const prange &r);

  enum value_range_kind m_kind : 3;

  // We don't use TRAILING_WIDE_INT_ACCESSOR because the getters here
  // must be const.  Perhaps TRAILING_WIDE_INT_ACCESSOR could be made
  // const and return wide_int instead of trailing_wide_int.
  wide_int get_low () const { return m_trailing_ints[0]; }
  wide_int get_high () const { return m_trailing_ints[1]; }
  wide_int get_value () const { return m_trailing_ints[2]; }
  wide_int get_mask () const { return m_trailing_ints[3]; }
  template <typename T> void set_low (const T &x) { m_trailing_ints[0] = x; }
  template <typename T> void set_high (const T &x) { m_trailing_ints[1] = x; }
  template <typename T> void set_value (const T &x) { m_trailing_ints[2] = x; }
  template <typename T> void set_mask (const T &x) { m_trailing_ints[3] = x; }

  static const unsigned int NINTS = 4;
  trailing_wide_ints<NINTS> m_trailing_ints;
};

// Efficient memory storage for an frange.

class frange_storage : public vrange_storage
{
 public:
  static frange_storage *alloc (vrange_internal_alloc &, const frange &r);
  void set_frange (const frange &r);
  void get_frange (frange &r, tree type) const;
  bool equal_p (const frange &r) const;
  bool fits_p (const frange &) const;
 private:
  frange_storage (const frange &r) { set_frange (r); }
  DISABLE_COPY_AND_ASSIGN (frange_storage);

  enum value_range_kind m_kind;
  REAL_VALUE_TYPE m_min;
  REAL_VALUE_TYPE m_max;
  bool m_pos_nan;
  bool m_neg_nan;
};

extern vrange_storage *ggc_alloc_vrange_storage (tree type);
extern vrange_storage *ggc_alloc_vrange_storage (const vrange &);

#endif // GCC_VALUE_RANGE_STORAGE_H