| /* Text art visualizations within -fanalyzer. | 
 |    Copyright (C) 2023-2025 Free Software Foundation, Inc. | 
 |    Contributed by David Malcolm <dmalcolm@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_ANALYZER_ACCESS_DIAGRAM_H | 
 | #define GCC_ANALYZER_ACCESS_DIAGRAM_H | 
 |  | 
 | #include "text-art/canvas.h" | 
 | #include "text-art/theme.h" | 
 | #include "text-art/widget.h" | 
 |  | 
 | #include "analyzer/store.h" | 
 |  | 
 | namespace ana { | 
 |  | 
 | class bit_size_expr | 
 | { | 
 | public: | 
 |   bit_size_expr (const svalue &num_bits) : m_num_bits (num_bits) {} | 
 |  | 
 |   std::unique_ptr<text_art::styled_string> | 
 |   maybe_get_formatted_str (text_art::style_manager &sm, | 
 | 			   const region_model &model, | 
 | 			   const char *concrete_single_bit_fmt, | 
 | 			   const char *concrete_plural_bits_fmt, | 
 | 			   const char *concrete_single_byte_fmt, | 
 | 			   const char *concrete_plural_bytes_fmt, | 
 | 			   const char *symbolic_bits_fmt, | 
 | 			   const char *symbolic_bytes_fmt) const; | 
 |   bool maybe_print_for_user (pretty_printer *pp, | 
 | 			     const region_model &model) const; | 
 |  | 
 |   const svalue *maybe_get_as_bytes (region_model_manager &mgr) const; | 
 |  | 
 | private: | 
 |   const svalue &m_num_bits; | 
 | }; | 
 |  | 
 | /* A range of bits within a base region, where each endpoint | 
 |    could be concrete or symbolic (not necessarily the same).  */ | 
 |  | 
 | struct access_range | 
 | { | 
 |   access_range () | 
 |   : m_start (), m_next () | 
 |   { | 
 |   } | 
 |   access_range (region_offset start, region_offset next, | 
 | 		region_model_manager &mgr) | 
 |   : m_start (strip_types (start, mgr)), m_next (strip_types (next, mgr)) | 
 |   {} | 
 |   access_range (const region *base_region, const bit_range &bits); | 
 |   access_range (const region *base_region, const byte_range &bytes); | 
 |   access_range (const region ®, region_model_manager *); | 
 |  | 
 |   bool concrete_p () const | 
 |   { | 
 |     return m_start.concrete_p () && m_next.concrete_p (); | 
 |   } | 
 |  | 
 |   bool empty_p () const; | 
 |  | 
 |   bit_size_expr get_size (region_model_manager *mgr) const; | 
 |  | 
 |   bool get_size_in_bits (bit_size_t *out) const | 
 |   { | 
 |     if (concrete_p ()) | 
 |       { | 
 | 	*out = m_next.get_bit_offset () - m_start.get_bit_offset (); | 
 | 	return true; | 
 |       } | 
 |     return false; | 
 |   } | 
 |  | 
 |   bool as_concrete_bit_range (bit_range *out) const | 
 |   { | 
 |     if (!concrete_p ()) | 
 |       return false; | 
 |     bit_size_t size = m_next.get_bit_offset () - m_start.get_bit_offset (); | 
 |     *out = bit_range (m_start.get_bit_offset (), size); | 
 |     return true; | 
 |   } | 
 |   bool as_concrete_byte_range (byte_range *out) const | 
 |   { | 
 |     bit_range bits (0, 0); | 
 |     if (!as_concrete_bit_range (&bits)) | 
 |       return false; | 
 |     return bits.as_byte_range (out); | 
 |   } | 
 |  | 
 |   bool contains_p (const access_range &other) const; | 
 |  | 
 |   void dump_to_pp (pretty_printer *pp, bool) const; | 
 |   void dump (bool) const; | 
 |   void log (const char *title, logger &) const; | 
 |  | 
 |   region_offset m_start; | 
 |   region_offset m_next; | 
 | }; | 
 |  | 
 | struct access_operation | 
 | { | 
 |   access_operation (const region_model &model, | 
 | 		    enum access_direction dir, | 
 | 		    const region ®, | 
 | 		    const svalue *sval_hint) | 
 |   : m_model (model), | 
 |     m_dir (dir), | 
 |     m_reg (reg), | 
 |     m_sval_hint (sval_hint), | 
 |     m_base_region (reg.get_base_region ()) | 
 |   {} | 
 |  | 
 |   region_model_manager *get_manager () const | 
 |   { | 
 |     return m_model.get_manager (); | 
 |   } | 
 |  | 
 |   /* Get the valid bits to access within the base region.  */ | 
 |   access_range get_valid_bits () const; | 
 |  | 
 |   /* Get the actual bits accessed within the base region.  */ | 
 |   access_range get_actual_bits () const; | 
 |  | 
 |   bool maybe_get_invalid_before_bits (access_range *out) const; | 
 |   bool maybe_get_invalid_after_bits (access_range *out) const; | 
 |  | 
 |   const region_model &m_model; | 
 |   enum access_direction m_dir; | 
 |   const region &m_reg; | 
 |   const svalue *m_sval_hint; | 
 |   const region *m_base_region; | 
 | }; | 
 |  | 
 | class access_diagram : public text_art::wrapper_widget | 
 | { | 
 | public: | 
 |   access_diagram (const access_operation &op, | 
 | 		  diagnostics::paths::event_id_t region_creation_event_id, | 
 | 		  text_art::style_manager &sm, | 
 | 		  const text_art::theme &theme, | 
 | 		  logger *logger); | 
 |   const char *get_desc () const override | 
 |   { | 
 |     return "access_diagram"; | 
 |   } | 
 | }; | 
 |  | 
 | } // namespace ana | 
 |  | 
 | #endif /* GCC_ANALYZER_ACCESS_DIAGRAM_H */ |