LCOV - code coverage report
Current view: top level - gcc - value-range-pretty-print.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.1 % 135 127
Test Date: 2026-08-01 15:33:25 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        83936 : print_int_bound (pretty_printer *pp, const wide_int &bound, tree type)
      35              : {
      36        83936 :   wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
      37        83936 :   wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
      38              : 
      39        83936 :   if (INTEGRAL_TYPE_P (type)
      40        81284 :       && !TYPE_UNSIGNED (type)
      41        24004 :       && bound == type_min
      42        84339 :       && TYPE_PRECISION (type) != 1)
      43          403 :     pp_string (pp, "-INF");
      44        83533 :   else if (bound == type_max && TYPE_PRECISION (type) != 1)
      45        12456 :     pp_string (pp, "+INF");
      46              :   else
      47        71077 :     pp_wide_int (pp, bound, TYPE_SIGN (type));
      48        83936 : }
      49              : 
      50              : static void
      51        39100 : print_irange_bitmasks (pretty_printer *pp, const irange_bitmask &bm)
      52              : {
      53        39100 :   if (bm.unknown_p ())
      54        31302 :     return;
      55              : 
      56         7798 :   pp_string (pp, " MASK ");
      57         7798 :   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
      58         7798 :   unsigned len_mask, len_val;
      59        15596 :   if (print_hex_buf_size (bm.mask (), &len_mask)
      60         7798 :       | print_hex_buf_size (bm.value (), &len_val))
      61            0 :     p = XALLOCAVEC (char, MAX (len_mask, len_val));
      62              :   else
      63              :     p = buf;
      64         7798 :   print_hex (bm.mask (), p);
      65         7798 :   pp_string (pp, p);
      66         7798 :   pp_string (pp, " VALUE ");
      67         7798 :   print_hex (bm.value (), p);
      68         7798 :   pp_string (pp, p);
      69              : }
      70              : 
      71              : void
      72          577 : vrange_printer::visit (const unsupported_range &r) const
      73              : {
      74          577 :   pp_string (pp, "[unsupported_range] ");
      75          577 :   if (r.undefined_p ())
      76              :     {
      77            0 :       pp_string (pp, "UNDEFINED");
      78            0 :       return;
      79              :     }
      80          577 :   if (r.varying_p ())
      81              :     {
      82          577 :       pp_string (pp, "VARYING");
      83          577 :       return;
      84              :     }
      85            0 :   gcc_unreachable ();
      86              : }
      87              : 
      88              : void
      89        38769 : vrange_printer::visit (const irange &r) const
      90              : {
      91        38769 :   pp_string (pp, "[irange] ");
      92        38769 :   if (r.undefined_p ())
      93              :     {
      94           16 :       pp_string (pp, "UNDEFINED");
      95           16 :       return;
      96              :     }
      97        38753 :   dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
      98        38753 :   pp_character (pp, ' ');
      99        38753 :   if (r.varying_p ())
     100              :     {
     101          979 :       pp_string (pp, "VARYING");
     102          979 :       return;
     103              :     }
     104        78416 :   for (unsigned i = 0; i < r.num_pairs (); ++i)
     105              :     {
     106        40642 :       pp_character (pp, '[');
     107        40642 :       print_int_bound (pp, r.lower_bound (i), r.type ());
     108        40642 :       pp_string (pp, ", ");
     109        40642 :       print_int_bound (pp, r.upper_bound (i), r.type ());
     110        40642 :       pp_character (pp, ']');
     111              :     }
     112        37774 :   print_irange_bitmasks (pp, r.m_bitmask);
     113              : }
     114              : 
     115              : void
     116         1326 : vrange_printer::print_pt (const prange &r) const
     117              : {
     118         1326 :   bool points_to_p = false;
     119         1326 :   tree pt = r.pt_invariant ();
     120              :   if (pt)
     121              :     points_to_p = true;
     122              :   else
     123          902 :     pt = r.pt_invariant_away ();
     124              : 
     125              :   if (pt)
     126              :     {
     127          424 :       if (points_to_p)
     128          424 :         pp_string (pp, " -> ");
     129              :       else
     130            0 :         pp_string (pp, " ! -> ");
     131          424 :       dump_generic_node (pp, pt, 0, TDF_NONE | TDF_NOUID, false);
     132          424 :       if (points_to_p)
     133              :         {
     134          424 :           int_range_max sz;
     135          424 :           int_range_max off;
     136          424 :           tree b;
     137          424 :           b = r.pt_base ();
     138          424 :           r.pt_offset(off);
     139          424 :           r.pt_size (sz);
     140          424 :           pp_string (pp, " { Base: ");
     141          424 :           dump_generic_node (pp, b, 0, TDF_NONE | TDF_NOUID, false);
     142          424 :           if (!off.varying_p () && !off.undefined_p () && !off.zero_p ())
     143              :             {
     144            0 :               pp_string (pp, " ; Off: ");
     145            0 :               visit (off);
     146              :             }
     147          424 :           if (!sz.varying_p () && !sz.undefined_p ())
     148              :               {
     149          424 :                 pp_string (pp, " ; Size: ");
     150          424 :                 visit (sz);
     151              :               }
     152          424 :           pp_string (pp, " }");
     153          424 :         }
     154              : 
     155              :     }
     156         1326 : }
     157              : 
     158              : void
     159         1434 : vrange_printer::visit (const prange &r) const
     160              : {
     161         1434 :   pp_string (pp, "[prange] ");
     162         1434 :   if (r.undefined_p ())
     163              :     {
     164            6 :       pp_string (pp, "UNDEFINED");
     165            6 :       return;
     166              :     }
     167         1428 :   dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
     168         1428 :   pp_character (pp, ' ');
     169         1428 :   if (r.varying_p ())
     170              :     {
     171          102 :       pp_string (pp, "VARYING");
     172          102 :       return;
     173              :     }
     174              : 
     175         1326 :   pp_character (pp, '[');
     176         1326 :   print_int_bound (pp, r.lower_bound (), r.type ());
     177         1326 :   pp_string (pp, ", ");
     178         1326 :   print_int_bound (pp, r.upper_bound (), r.type ());
     179         1326 :   pp_character (pp, ']');
     180         1326 :   print_irange_bitmasks (pp, r.m_bitmask);
     181              :   // Dump the points to field if there is one.
     182         1326 :   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 :   if (r.known_isnan ())
     223            3 :     pp_string (pp, "[]");
     224              :   else
     225          268 :     for (unsigned i = 0; i < r.num_pairs (); ++i)
     226              :       {
     227          134 :         pp_character (pp, '[');
     228          134 :         print_real_value (type, r.lower_bound (i));
     229          134 :         pp_string (pp, ", ");
     230          134 :         print_real_value (type, r.upper_bound (i));
     231          134 :         pp_character (pp, ']');
     232              :       }
     233          137 :   print_frange_nan (r);
     234              : }
     235              : 
     236              : // Print the NAN info for an frange.
     237              : 
     238              : void
     239          204 : vrange_printer::print_frange_nan (const frange &r) const
     240              : {
     241          331 :   if (r.maybe_isnan ())
     242              :     {
     243           77 :       if (r.m_pos_nan && r.m_neg_nan)
     244              :         {
     245           64 :           pp_string (pp, " +-NAN");
     246           64 :           return;
     247              :         }
     248           13 :       bool nan_sign = r.m_neg_nan;
     249           13 :       if (nan_sign)
     250            0 :         pp_string (pp, " -NAN");
     251              :       else
     252           13 :         pp_string (pp, " +NAN");
     253              :     }
     254              : }
        

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.