LCOV - code coverage report
Current view: top level - lib/Support - NativeFormatting.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 85 89 95.5 %
Date: 2018-06-17 00:07:59 Functions: 18 19 94.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- NativeFormatting.cpp - Low level formatting helpers -------*- C++-*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/Support/NativeFormatting.h"
      11             : 
      12             : #include "llvm/ADT/ArrayRef.h"
      13             : #include "llvm/ADT/SmallString.h"
      14             : #include "llvm/ADT/StringExtras.h"
      15             : #include "llvm/Support/Format.h"
      16             : 
      17             : #include <float.h>
      18             : 
      19             : using namespace llvm;
      20             : 
      21             : template<typename T, std::size_t N>
      22             : static int format_to_buffer(T Value, char (&Buffer)[N]) {
      23             :   char *EndPtr = std::end(Buffer);
      24             :   char *CurPtr = EndPtr;
      25             : 
      26   129306677 :   do {
      27   129306677 :     *--CurPtr = '0' + char(Value % 10);
      28   129306677 :     Value /= 10;
      29             :   } while (Value);
      30    56121640 :   return EndPtr - CurPtr;
      31             : }
      32             : 
      33          90 : static void writeWithCommas(raw_ostream &S, ArrayRef<char> Buffer) {
      34             :   assert(!Buffer.empty());
      35             : 
      36             :   ArrayRef<char> ThisGroup;
      37          90 :   int InitialDigits = ((Buffer.size() - 1) % 3) + 1;
      38          90 :   ThisGroup = Buffer.take_front(InitialDigits);
      39          90 :   S.write(ThisGroup.data(), ThisGroup.size());
      40             : 
      41             :   Buffer = Buffer.drop_front(InitialDigits);
      42             :   assert(Buffer.size() % 3 == 0);
      43         176 :   while (!Buffer.empty()) {
      44             :     S << ',';
      45             :     ThisGroup = Buffer.take_front(3);
      46          43 :     S.write(ThisGroup.data(), 3);
      47             :     Buffer = Buffer.drop_front(3);
      48             :   }
      49          90 : }
      50             : 
      51             : template <typename T>
      52    56121640 : static void write_unsigned_impl(raw_ostream &S, T N, size_t MinDigits,
      53             :                                 IntegerStyle Style, bool IsNegative) {
      54             :   static_assert(std::is_unsigned<T>::value, "Value is not unsigned!");
      55             : 
      56             :   char NumberBuffer[128];
      57    56121640 :   std::memset(NumberBuffer, '0', sizeof(NumberBuffer));
      58             : 
      59             :   size_t Len = 0;
      60    56121640 :   Len = format_to_buffer(N, NumberBuffer);
      61             : 
      62    56121640 :   if (IsNegative)
      63             :     S << '-';
      64             : 
      65    56121640 :   if (Len < MinDigits && Style != IntegerStyle::Number) {
      66        3255 :     for (size_t I = Len; I < MinDigits; ++I)
      67             :       S << '0';
      68             :   }
      69             : 
      70    56121640 :   if (Style == IntegerStyle::Number) {
      71         180 :     writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len));
      72             :   } else {
      73    56121550 :     S.write(std::end(NumberBuffer) - Len, Len);
      74             :   }
      75    56121636 : }
      76             : 
      77             : template <typename T>
      78    56111140 : static void write_unsigned(raw_ostream &S, T N, size_t MinDigits,
      79             :                            IntegerStyle Style, bool IsNegative = false) {
      80             :   // Output using 32-bit div/mod if possible.
      81    56111140 :   if (N == static_cast<uint32_t>(N))
      82    56085532 :     write_unsigned_impl(S, static_cast<uint32_t>(N), MinDigits, Style,
      83             :                         IsNegative);
      84             :   else
      85       36106 :     write_unsigned_impl(S, N, MinDigits, Style, IsNegative);
      86    56111138 : }
      87             : 
      88             : template <typename T>
      89    18457681 : static void write_signed(raw_ostream &S, T N, size_t MinDigits,
      90             :                          IntegerStyle Style) {
      91             :   static_assert(std::is_signed<T>::value, "Value is not signed!");
      92             : 
      93             :   using UnsignedT = typename std::make_unsigned<T>::type;
      94             : 
      95    18457681 :   if (N >= 0) {
      96    18024492 :     write_unsigned(S, static_cast<UnsignedT>(N), MinDigits, Style);
      97    18019970 :     return;
      98             :   }
      99             : 
     100      433189 :   UnsignedT UN = -(UnsignedT)N;
     101      432895 :   write_unsigned(S, UN, MinDigits, Style, true);
     102             : }
     103             : 
     104        5684 : void llvm::write_integer(raw_ostream &S, unsigned int N, size_t MinDigits,
     105             :                          IntegerStyle Style) {
     106             :   write_unsigned(S, N, MinDigits, Style);
     107        5684 : }
     108             : 
     109        4814 : void llvm::write_integer(raw_ostream &S, int N, size_t MinDigits,
     110             :                          IntegerStyle Style) {
     111        4814 :   write_signed(S, N, MinDigits, Style);
     112        4814 : }
     113             : 
     114    37658274 : void llvm::write_integer(raw_ostream &S, unsigned long N, size_t MinDigits,
     115             :                          IntegerStyle Style) {
     116    37658274 :   write_unsigned(S, N, MinDigits, Style);
     117    37658275 : }
     118             : 
     119    18452810 : void llvm::write_integer(raw_ostream &S, long N, size_t MinDigits,
     120             :                          IntegerStyle Style) {
     121    18452810 :   write_signed(S, N, MinDigits, Style);
     122    18452807 : }
     123             : 
     124           0 : void llvm::write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits,
     125             :                          IntegerStyle Style) {
     126           0 :   write_unsigned(S, N, MinDigits, Style);
     127           0 : }
     128             : 
     129          57 : void llvm::write_integer(raw_ostream &S, long long N, size_t MinDigits,
     130             :                          IntegerStyle Style) {
     131          57 :   write_signed(S, N, MinDigits, Style);
     132          57 : }
     133             : 
     134    30113986 : void llvm::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
     135             :                      Optional<size_t> Width) {
     136    30113986 :   const size_t kMaxWidth = 128u;
     137             : 
     138    60227972 :   size_t W = std::min(kMaxWidth, Width.getValueOr(0u));
     139             : 
     140    30113986 :   unsigned Nibbles = (64 - countLeadingZeros(N) + 3) / 4;
     141    30113986 :   bool Prefix = (Style == HexPrintStyle::PrefixLower ||
     142             :                  Style == HexPrintStyle::PrefixUpper);
     143    30113986 :   bool Upper =
     144    30113986 :       (Style == HexPrintStyle::Upper || Style == HexPrintStyle::PrefixUpper);
     145    30113986 :   unsigned PrefixChars = Prefix ? 2 : 0;
     146             :   unsigned NumChars =
     147    90341958 :       std::max(static_cast<unsigned>(W), std::max(1u, Nibbles) + PrefixChars);
     148             : 
     149             :   char NumberBuffer[kMaxWidth];
     150    30113986 :   ::memset(NumberBuffer, '0', llvm::array_lengthof(NumberBuffer));
     151    30113986 :   if (Prefix)
     152       25262 :     NumberBuffer[1] = 'x';
     153    30113986 :   char *EndPtr = NumberBuffer + NumChars;
     154             :   char *CurPtr = EndPtr;
     155   122280792 :   while (N) {
     156    46083403 :     unsigned char x = static_cast<unsigned char>(N) % 16;
     157    92166806 :     *--CurPtr = hexdigit(x, !Upper);
     158    46083403 :     N /= 16;
     159             :   }
     160             : 
     161    30113986 :   S.write(NumberBuffer, NumChars);
     162    30113986 : }
     163             : 
     164       30662 : void llvm::write_double(raw_ostream &S, double N, FloatStyle Style,
     165             :                         Optional<size_t> Precision) {
     166       30662 :   size_t Prec = Precision.getValueOr(getDefaultPrecision(Style));
     167             : 
     168             :   if (std::isnan(N)) {
     169         719 :     S << "nan";
     170         719 :     return;
     171       29943 :   } else if (std::isinf(N)) {
     172          28 :     S << "INF";
     173          28 :     return;
     174             :   }
     175             : 
     176             :   char Letter;
     177       29915 :   if (Style == FloatStyle::Exponent)
     178             :     Letter = 'e';
     179         372 :   else if (Style == FloatStyle::ExponentUpper)
     180             :     Letter = 'E';
     181             :   else
     182             :     Letter = 'f';
     183             : 
     184             :   SmallString<8> Spec;
     185             :   llvm::raw_svector_ostream Out(Spec);
     186       29915 :   Out << "%." << Prec << Letter;
     187             : 
     188             :   if (Style == FloatStyle::Exponent || Style == FloatStyle::ExponentUpper) {
     189             : #ifdef _WIN32
     190             : // On MSVCRT and compatible, output of %e is incompatible to Posix
     191             : // by default. Number of exponent digits should be at least 2. "%+03d"
     192             : // FIXME: Implement our formatter to here or Support/Format.h!
     193             : #if defined(__MINGW32__)
     194             :     // FIXME: It should be generic to C++11.
     195             :     if (N == 0.0 && std::signbit(N)) {
     196             :       char NegativeZero[] = "-0.000000e+00";
     197             :       if (Style == FloatStyle::ExponentUpper)
     198             :         NegativeZero[strlen(NegativeZero) - 4] = 'E';
     199             :       S << NegativeZero;
     200             :       return;
     201             :     }
     202             : #else
     203             :     int fpcl = _fpclass(N);
     204             : 
     205             :     // negative zero
     206             :     if (fpcl == _FPCLASS_NZ) {
     207             :       char NegativeZero[] = "-0.000000e+00";
     208             :       if (Style == FloatStyle::ExponentUpper)
     209             :         NegativeZero[strlen(NegativeZero) - 4] = 'E';
     210             :       S << NegativeZero;
     211             :       return;
     212             :     }
     213             : #endif
     214             : 
     215             :     char buf[32];
     216             :     unsigned len;
     217             :     len = format(Spec.c_str(), N).snprint(buf, sizeof(buf));
     218             :     if (len <= sizeof(buf) - 2) {
     219             :       if (len >= 5 && (buf[len - 5] == 'e' || buf[len - 5] == 'E') &&
     220             :           buf[len - 3] == '0') {
     221             :         int cs = buf[len - 4];
     222             :         if (cs == '+' || cs == '-') {
     223             :           int c1 = buf[len - 2];
     224             :           int c0 = buf[len - 1];
     225             :           if (isdigit(static_cast<unsigned char>(c1)) &&
     226             :               isdigit(static_cast<unsigned char>(c0))) {
     227             :             // Trim leading '0': "...e+012" -> "...e+12\0"
     228             :             buf[len - 3] = c1;
     229             :             buf[len - 2] = c0;
     230             :             buf[--len] = 0;
     231             :           }
     232             :         }
     233             :       }
     234             :       S << buf;
     235             :       return;
     236             :     }
     237             : #endif
     238             :   }
     239             : 
     240       29915 :   if (Style == FloatStyle::Percent)
     241          84 :     N *= 100.0;
     242             : 
     243             :   char Buf[32];
     244             :   format(Spec.c_str(), N).snprint(Buf, sizeof(Buf));
     245       29915 :   S << Buf;
     246       29915 :   if (Style == FloatStyle::Percent)
     247             :     S << '%';
     248             : }
     249             : 
     250        6244 : bool llvm::isPrefixedHexStyle(HexPrintStyle S) {
     251        6244 :   return (S == HexPrintStyle::PrefixLower || S == HexPrintStyle::PrefixUpper);
     252             : }
     253             : 
     254       30853 : size_t llvm::getDefaultPrecision(FloatStyle Style) {
     255       30853 :   switch (Style) {
     256             :   case FloatStyle::Exponent:
     257             :   case FloatStyle::ExponentUpper:
     258             :     return 6; // Number of decimal places.
     259         544 :   case FloatStyle::Fixed:
     260             :   case FloatStyle::Percent:
     261         544 :     return 2; // Number of decimal places.
     262             :   }
     263           0 :   LLVM_BUILTIN_UNREACHABLE;
     264             : }

Generated by: LCOV version 1.13