LCOV - code coverage report
Current view: top level - gcc - value-range-pretty-print.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.0 % 134 126
Test Date: 2026-06-20 15:32:29 Functions: 100.0 % 9 9
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Pretty print support for value ranges.
       2              :    Copyright (C) 2019-2026 Free Software Foundation, Inc.
       3              :    Contributed by Aldy Hernandez <aldyh@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       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.
      11              : 
      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.
      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              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "backend.h"
      25              : #include "tree.h"
      26              : #include "gimple.h"
      27              : #include "ssa.h"
      28              : #include "tree-pretty-print.h"
      29              : #include "fold-const.h"
      30              : #include "gimple-range.h"
      31              : #include "value-range-pretty-print.h"
      32              : 
      33              : static void
      34        83910 : print_int_bound (pretty_printer *pp, const wide_int &bound, tree type)
      35              : {
      36        83910 :   wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
      37        83910 :   wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
      38              : 
      39        83910 :   if (INTEGRAL_TYPE_P (type)
      40        81262 :       && !TYPE_UNSIGNED (type)
      41        24124 :       && bound == type_min
      42        84313 :       && TYPE_PRECISION (type) != 1)
      43          403 :     pp_string (pp, "-INF");
      44        83507 :   else if (bound == type_max && TYPE_PRECISION (type) != 1)
      45        12463 :     pp_string (pp, "+INF");
      46              :   else
      47        71044 :     pp_wide_int (pp, bound, TYPE_SIGN (type));
      48        83910 : }
      49              : 
      50              : static void
      51        39136 : print_irange_bitmasks (pretty_printer *pp, const irange_bitmask &bm)
      52              : {
      53        39136 :   if (bm.unknown_p ())
      54        31282 :     return;
      55              : 
      56         7854 :   pp_string (pp, " MASK ");
      57         7854 :   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
      58         7854 :   unsigned len_mask, len_val;
      59        15708 :   if (print_hex_buf_size (bm.mask (), &len_mask)
      60         7854 :       | print_hex_buf_size (bm.value (), &len_val))
      61            0 :     p = XALLOCAVEC (char, MAX (len_mask, len_val));
      62              :   else
      63              :     p = buf;
      64         7854 :   print_hex (bm.mask (), p);
      65         7854 :   pp_string (pp, p);
      66         7854 :   pp_string (pp, " VALUE ");
      67         7854 :   print_hex (bm.value (), p);
      68         7854 :   pp_string (pp, p);
      69              : }
      70              : 
      71              : void
      72          578 : vrange_printer::visit (const unsupported_range &r) const
      73              : {
      74          578 :   pp_string (pp, "[unsupported_range] ");
      75          578 :   if (r.undefined_p ())
      76              :     {
      77            0 :       pp_string (pp, "UNDEFINED");
      78            0 :       return;
      79              :     }
      80          578 :   if (r.varying_p ())
      81              :     {
      82          578 :       pp_string (pp, "VARYING");
      83          578 :       return;
      84              :     }
      85            0 :   gcc_unreachable ();
      86              : }
      87              : 
      88              : void
      89        38808 : vrange_printer::visit (const irange &r) const
      90              : {
      91        38808 :   pp_string (pp, "[irange] ");
      92        38808 :   if (r.undefined_p ())
      93              :     {
      94           16 :       pp_string (pp, "UNDEFINED");
      95           16 :       return;
      96              :     }
      97        38792 :   dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
      98        38792 :   pp_character (pp, ' ');
      99        38792 :   if (r.varying_p ())
     100              :     {
     101          980 :       pp_string (pp, "VARYING");
     102          980 :       return;
     103              :     }
     104        78443 :   for (unsigned i = 0; i < r.num_pairs (); ++i)
     105              :     {
     106        40631 :       pp_character (pp, '[');
     107        40631 :       print_int_bound (pp, r.lower_bound (i), r.type ());
     108        40631 :       pp_string (pp, ", ");
     109        40631 :       print_int_bound (pp, r.upper_bound (i), r.type ());
     110        40631 :       pp_character (pp, ']');
     111              :     }
     112        37812 :   print_irange_bitmasks (pp, r.m_bitmask);
     113              : }
     114              : 
     115              : void
     116         1324 : vrange_printer::print_pt (const prange &r) const
     117              : {
     118         1324 :   bool points_to_p = false;
     119         1324 :   tree pt = r.pt_invariant ();
     120              :   if (pt)
     121              :     points_to_p = true;
     122              :   else
     123          927 :     pt = r.pt_invariant_away ();
     124              : 
     125              :   if (pt)
     126              :     {
     127          397 :       if (points_to_p)
     128          397 :         pp_string (pp, " -> ");
     129              :       else
     130            0 :         pp_string (pp, " ! -> ");
     131          397 :       dump_generic_node (pp, pt, 0, TDF_NONE | TDF_NOUID, false);
     132          397 :       if (points_to_p)
     133              :         {
     134          397 :           int_range_max sz;
     135          397 :           int_range_max off;
     136          397 :           tree b;
     137          397 :           b = r.pt_base ();
     138          397 :           r.pt_offset(off);
     139          397 :           r.pt_size (sz);
     140          397 :           pp_string (pp, " { Base: ");
     141          397 :           dump_generic_node (pp, b, 0, TDF_NONE | TDF_NOUID, false);
     142          397 :           if (!off.varying_p () && !off.undefined_p () && !off.zero_p ())
     143              :             {
     144            0 :               pp_string (pp, " ; Off: ");
     145            0 :               visit (off);
     146              :             }
     147          397 :           if (!sz.varying_p () && !sz.undefined_p ())
     148              :               {
     149          397 :                 pp_string (pp, " ; Size: ");
     150          397 :                 visit (sz);
     151              :               }
     152          397 :           pp_string (pp, " }");
     153          397 :         }
     154              : 
     155              :     }
     156         1324 : }
     157              : 
     158              : void
     159         1432 : vrange_printer::visit (const prange &r) const
     160              : {
     161         1432 :   pp_string (pp, "[prange] ");
     162         1432 :   if (r.undefined_p ())
     163              :     {
     164            6 :       pp_string (pp, "UNDEFINED");
     165            6 :       return;
     166              :     }
     167         1426 :   dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
     168         1426 :   pp_character (pp, ' ');
     169         1426 :   if (r.varying_p ())
     170              :     {
     171          102 :       pp_string (pp, "VARYING");
     172          102 :       return;
     173              :     }
     174              : 
     175         1324 :   pp_character (pp, '[');
     176         1324 :   print_int_bound (pp, r.lower_bound (), r.type ());
     177         1324 :   pp_string (pp, ", ");
     178         1324 :   print_int_bound (pp, r.upper_bound (), r.type ());
     179         1324 :   pp_character (pp, ']');
     180         1324 :   print_irange_bitmasks (pp, r.m_bitmask);
     181              :   // Dump the points to field if there is one.
     182         1324 :   print_pt (r);
     183              : }
     184              : 
     185              : void
     186          268 : vrange_printer::print_real_value (tree type, const REAL_VALUE_TYPE &r) const
     187              : {
     188          268 :   char s[100];
     189          268 :   real_to_decimal_for_mode (s, &r, sizeof (s), 0, 1, TYPE_MODE (type));
     190          268 :   pp_string (pp, s);
     191          268 :   if (!DECIMAL_FLOAT_TYPE_P (type)
     192              :       // real_to_hexadecimal prints infinities and NAN as text.  No
     193              :       // need to print them twice.
     194          268 :       && !real_isinf (&r)
     195          462 :       && !real_isnan (&r))
     196              :     {
     197          194 :       real_to_hexadecimal (s, &r, sizeof (s), 0, 1);
     198          194 :       pp_printf (pp, " (%s)", s);
     199              :     }
     200          268 : }
     201              : 
     202              : // Print an frange.
     203              : 
     204              : void
     205          209 : vrange_printer::visit (const frange &r) const
     206              : {
     207          209 :   pp_string (pp, "[frange] ");
     208          209 :   if (r.undefined_p ())
     209              :     {
     210            5 :       pp_string (pp, "UNDEFINED");
     211            5 :       return;
     212              :     }
     213          204 :   tree type = r.type ();
     214          204 :   dump_generic_node (pp, type, 0, TDF_NONE, false);
     215          204 :   pp_string (pp, " ");
     216          204 :   if (r.varying_p ())
     217              :     {
     218           67 :       pp_string (pp, "VARYING");
     219           67 :       print_frange_nan (r);
     220           67 :       return;
     221              :     }
     222          137 :   pp_character (pp, '[');
     223          137 :   bool has_endpoints = !r.known_isnan ();
     224          137 :   if (has_endpoints)
     225              :     {
     226          134 :       print_real_value (type, r.lower_bound ());
     227          134 :       pp_string (pp, ", ");
     228          134 :       print_real_value (type, r.upper_bound ());
     229              :     }
     230          137 :   pp_character (pp, ']');
     231          137 :   print_frange_nan (r);
     232              : }
     233              : 
     234              : // Print the NAN info for an frange.
     235              : 
     236              : void
     237          204 : vrange_printer::print_frange_nan (const frange &r) const
     238              : {
     239          331 :   if (r.maybe_isnan ())
     240              :     {
     241           77 :       if (r.m_pos_nan && r.m_neg_nan)
     242              :         {
     243           64 :           pp_string (pp, " +-NAN");
     244           64 :           return;
     245              :         }
     246           13 :       bool nan_sign = r.m_neg_nan;
     247           13 :       if (nan_sign)
     248            0 :         pp_string (pp, " -NAN");
     249              :       else
     250           13 :         pp_string (pp, " +NAN");
     251              :     }
     252              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.