1 | /* Text art visualizations within -fanalyzer. |
2 | Copyright (C) 2023-2024 Free Software Foundation, Inc. |
3 | Contributed by David Malcolm <dmalcolm@redhat.com>. |
4 | |
5 | This file is part of GCC. |
6 | |
7 | GCC is free software; you can redistribute it and/or modify it |
8 | 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. |
11 | |
12 | GCC is distributed in the hope that it will be useful, but |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | General Public License for more details. |
16 | |
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/>. */ |
20 | |
21 | #ifndef GCC_ANALYZER_ACCESS_DIAGRAM_H |
22 | #define GCC_ANALYZER_ACCESS_DIAGRAM_H |
23 | |
24 | #include "text-art/canvas.h" |
25 | #include "text-art/theme.h" |
26 | #include "text-art/widget.h" |
27 | #include "analyzer/analyzer.h" |
28 | #include "analyzer/store.h" |
29 | |
30 | namespace ana { |
31 | |
32 | class bit_size_expr |
33 | { |
34 | public: |
35 | bit_size_expr (const svalue &num_bits) : m_num_bits (num_bits) {} |
36 | |
37 | std::unique_ptr<text_art::styled_string> |
38 | maybe_get_formatted_str (text_art::style_manager &sm, |
39 | const region_model &model, |
40 | const char *concrete_single_bit_fmt, |
41 | const char *concrete_plural_bits_fmt, |
42 | const char *concrete_single_byte_fmt, |
43 | const char *concrete_plural_bytes_fmt, |
44 | const char *symbolic_bits_fmt, |
45 | const char *symbolic_bytes_fmt) const; |
46 | bool maybe_print_for_user (pretty_printer *pp, |
47 | const region_model &model) const; |
48 | |
49 | const svalue *maybe_get_as_bytes (region_model_manager &mgr) const; |
50 | |
51 | private: |
52 | const svalue &m_num_bits; |
53 | }; |
54 | |
55 | /* A range of bits within a base region, where each endpoint |
56 | could be concrete or symbolic (not necessarily the same). */ |
57 | |
58 | struct access_range |
59 | { |
60 | access_range () |
61 | : m_start (), m_next () |
62 | { |
63 | } |
64 | access_range (region_offset start, region_offset next, |
65 | region_model_manager &mgr) |
66 | : m_start (strip_types (offset: start, mgr)), m_next (strip_types (offset: next, mgr)) |
67 | {} |
68 | access_range (const region *base_region, const bit_range &bits); |
69 | access_range (const region *base_region, const byte_range &bytes); |
70 | access_range (const region ®, region_model_manager *); |
71 | |
72 | bool concrete_p () const |
73 | { |
74 | return m_start.concrete_p () && m_next.concrete_p (); |
75 | } |
76 | |
77 | bool empty_p () const; |
78 | |
79 | bit_size_expr get_size (region_model_manager *mgr) const; |
80 | |
81 | bool get_size_in_bits (bit_size_t *out) const |
82 | { |
83 | if (concrete_p ()) |
84 | { |
85 | *out = m_next.get_bit_offset () - m_start.get_bit_offset (); |
86 | return true; |
87 | } |
88 | return false; |
89 | } |
90 | |
91 | bool as_concrete_bit_range (bit_range *out) const |
92 | { |
93 | if (!concrete_p ()) |
94 | return false; |
95 | bit_size_t size = m_next.get_bit_offset () - m_start.get_bit_offset (); |
96 | *out = bit_range (m_start.get_bit_offset (), size); |
97 | return true; |
98 | } |
99 | bool as_concrete_byte_range (byte_range *out) const |
100 | { |
101 | bit_range bits (0, 0); |
102 | if (!as_concrete_bit_range (out: &bits)) |
103 | return false; |
104 | return bits.as_byte_range (out); |
105 | } |
106 | |
107 | bool contains_p (const access_range &other) const; |
108 | |
109 | void dump_to_pp (pretty_printer *pp, bool) const; |
110 | void dump (bool) const; |
111 | void log (const char *title, logger &) const; |
112 | |
113 | region_offset m_start; |
114 | region_offset m_next; |
115 | }; |
116 | |
117 | struct access_operation |
118 | { |
119 | access_operation (const region_model &model, |
120 | enum access_direction dir, |
121 | const region ®, |
122 | const svalue *sval_hint) |
123 | : m_model (model), |
124 | m_dir (dir), |
125 | m_reg (reg), |
126 | m_sval_hint (sval_hint), |
127 | m_base_region (reg.get_base_region ()) |
128 | {} |
129 | |
130 | region_model_manager *get_manager () const |
131 | { |
132 | return m_model.get_manager (); |
133 | } |
134 | |
135 | /* Get the valid bits to access within the base region. */ |
136 | access_range get_valid_bits () const; |
137 | |
138 | /* Get the actual bits accessed within the base region. */ |
139 | access_range get_actual_bits () const; |
140 | |
141 | bool maybe_get_invalid_before_bits (access_range *out) const; |
142 | bool maybe_get_invalid_after_bits (access_range *out) const; |
143 | |
144 | const region_model &m_model; |
145 | enum access_direction m_dir; |
146 | const region &m_reg; |
147 | const svalue *m_sval_hint; |
148 | const region *m_base_region; |
149 | }; |
150 | |
151 | class access_diagram : public text_art::wrapper_widget |
152 | { |
153 | public: |
154 | access_diagram (const access_operation &op, |
155 | diagnostic_event_id_t region_creation_event_id, |
156 | text_art::style_manager &sm, |
157 | const text_art::theme &theme, |
158 | logger *logger); |
159 | const char *get_desc () const override |
160 | { |
161 | return "access_diagram" ; |
162 | } |
163 | }; |
164 | |
165 | } // namespace ana |
166 | |
167 | #endif /* GCC_ANALYZER_ACCESS_DIAGRAM_H */ |
168 | |