LCOV - code coverage report
Current view: top level - lib/Support - NativeFormatting.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 101 105 96.2 %
Date: 2017-09-14 15:23:50 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             : using namespace llvm;
      18             : 
      19             : template<typename T, std::size_t N>
      20             : static int format_to_buffer(T Value, char (&Buffer)[N]) {
      21    44347551 :   char *EndPtr = std::end(Buffer);
      22    44347551 :   char *CurPtr = EndPtr;
      23             : 
      24   105905342 :   do {
      25   105905342 :     *--CurPtr = '0' + char(Value % 10);
      26   105905342 :     Value /= 10;
      27             :   } while (Value);
      28    44347551 :   return EndPtr - CurPtr;
      29             : }
      30             : 
      31          82 : static void writeWithCommas(raw_ostream &S, ArrayRef<char> Buffer) {
      32             :   assert(!Buffer.empty());
      33             : 
      34          82 :   ArrayRef<char> ThisGroup;
      35          82 :   int InitialDigits = ((Buffer.size() - 1) % 3) + 1;
      36         164 :   ThisGroup = Buffer.take_front(InitialDigits);
      37          82 :   S.write(ThisGroup.data(), ThisGroup.size());
      38             : 
      39         164 :   Buffer = Buffer.drop_front(InitialDigits);
      40             :   assert(Buffer.size() % 3 == 0);
      41         168 :   while (!Buffer.empty()) {
      42          43 :     S << ',';
      43          43 :     ThisGroup = Buffer.take_front(3);
      44          43 :     S.write(ThisGroup.data(), 3);
      45          43 :     Buffer = Buffer.drop_front(3);
      46             :   }
      47          82 : }
      48             : 
      49             : template <typename T>
      50    44347551 : static void write_unsigned_impl(raw_ostream &S, T N, size_t MinDigits,
      51             :                                 IntegerStyle Style, bool IsNegative) {
      52             :   static_assert(std::is_unsigned<T>::value, "Value is not unsigned!");
      53             : 
      54             :   char NumberBuffer[128];
      55    44347551 :   std::memset(NumberBuffer, '0', sizeof(NumberBuffer));
      56             : 
      57    44347551 :   size_t Len = 0;
      58    44347551 :   Len = format_to_buffer(N, NumberBuffer);
      59             : 
      60    44347551 :   if (IsNegative)
      61             :     S << '-';
      62             : 
      63    44347551 :   if (Len < MinDigits && Style != IntegerStyle::Number) {
      64        2709 :     for (size_t I = Len; I < MinDigits; ++I)
      65        1135 :       S << '0';
      66             :   }
      67             : 
      68    44347551 :   if (Style == IntegerStyle::Number) {
      69         164 :     writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len));
      70             :   } else {
      71    44347469 :     S.write(std::end(NumberBuffer) - Len, Len);
      72             :   }
      73    44347551 : }
      74             : 
      75             : template <typename T>
      76    44343729 : static void write_unsigned(raw_ostream &S, T N, size_t MinDigits,
      77             :                            IntegerStyle Style, bool IsNegative = false) {
      78             :   // Output using 32-bit div/mod if possible.
      79    44343729 :   if (N == static_cast<uint32_t>(N))
      80    44326862 :     write_unsigned_impl(S, static_cast<uint32_t>(N), MinDigits, Style,
      81             :                         IsNegative);
      82             :   else
      83       20689 :     write_unsigned_impl(S, N, MinDigits, Style, IsNegative);
      84    44343729 : }
      85             : 
      86             : template <typename T>
      87     6211048 : static void write_signed(raw_ostream &S, T N, size_t MinDigits,
      88             :                          IntegerStyle Style) {
      89             :   static_assert(std::is_signed<T>::value, "Value is not signed!");
      90             : 
      91             :   using UnsignedT = typename std::make_unsigned<T>::type;
      92             : 
      93     6211048 :   if (N >= 0) {
      94     5887634 :     write_unsigned(S, static_cast<UnsignedT>(N), MinDigits, Style);
      95     5886319 :     return;
      96             :   }
      97             : 
      98      323414 :   UnsignedT UN = -(UnsignedT)N;
      99      323315 :   write_unsigned(S, UN, MinDigits, Style, true);
     100             : }
     101             : 
     102        2408 : void llvm::write_integer(raw_ostream &S, unsigned int N, size_t MinDigits,
     103             :                          IntegerStyle Style) {
     104        2408 :   write_unsigned(S, N, MinDigits, Style);
     105        2408 : }
     106             : 
     107        1414 : void llvm::write_integer(raw_ostream &S, int N, size_t MinDigits,
     108             :                          IntegerStyle Style) {
     109        1414 :   write_signed(S, N, MinDigits, Style);
     110        1414 : }
     111             : 
     112    38134095 : void llvm::write_integer(raw_ostream &S, unsigned long N, size_t MinDigits,
     113             :                          IntegerStyle Style) {
     114    38134095 :   write_unsigned(S, N, MinDigits, Style);
     115    38134095 : }
     116             : 
     117     6209577 : void llvm::write_integer(raw_ostream &S, long N, size_t MinDigits,
     118             :                          IntegerStyle Style) {
     119     6209577 :   write_signed(S, N, MinDigits, Style);
     120     6209577 : }
     121             : 
     122           0 : void llvm::write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits,
     123             :                          IntegerStyle Style) {
     124           0 :   write_unsigned(S, N, MinDigits, Style);
     125           0 : }
     126             : 
     127          57 : void llvm::write_integer(raw_ostream &S, long long N, size_t MinDigits,
     128             :                          IntegerStyle Style) {
     129          57 :   write_signed(S, N, MinDigits, Style);
     130          57 : }
     131             : 
     132    29656689 : void llvm::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
     133             :                      Optional<size_t> Width) {
     134    29656689 :   const size_t kMaxWidth = 128u;
     135             : 
     136    88970067 :   size_t W = std::min(kMaxWidth, Width.getValueOr(0u));
     137             : 
     138    29656689 :   unsigned Nibbles = (64 - countLeadingZeros(N) + 3) / 4;
     139    29656689 :   bool Prefix = (Style == HexPrintStyle::PrefixLower ||
     140             :                  Style == HexPrintStyle::PrefixUpper);
     141    29656689 :   bool Upper =
     142    29656689 :       (Style == HexPrintStyle::Upper || Style == HexPrintStyle::PrefixUpper);
     143    29656689 :   unsigned PrefixChars = Prefix ? 2 : 0;
     144             :   unsigned NumChars =
     145    88970067 :       std::max(static_cast<unsigned>(W), std::max(1u, Nibbles) + PrefixChars);
     146             : 
     147             :   char NumberBuffer[kMaxWidth];
     148    29656689 :   ::memset(NumberBuffer, '0', llvm::array_lengthof(NumberBuffer));
     149    29656689 :   if (Prefix)
     150       17385 :     NumberBuffer[1] = 'x';
     151    29656689 :   char *EndPtr = NumberBuffer + NumChars;
     152    29656689 :   char *CurPtr = EndPtr;
     153   119682201 :   while (N) {
     154    45012756 :     unsigned char x = static_cast<unsigned char>(N) % 16;
     155    90025512 :     *--CurPtr = hexdigit(x, !Upper);
     156    45012756 :     N /= 16;
     157             :   }
     158             : 
     159    29656689 :   S.write(NumberBuffer, NumChars);
     160    29656689 : }
     161             : 
     162       28858 : void llvm::write_double(raw_ostream &S, double N, FloatStyle Style,
     163             :                         Optional<size_t> Precision) {
     164       57716 :   size_t Prec = Precision.getValueOr(getDefaultPrecision(Style));
     165             : 
     166       57716 :   if (std::isnan(N)) {
     167         652 :     S << "nan";
     168         652 :     return;
     169       56412 :   } else if (std::isinf(N)) {
     170          28 :     S << "INF";
     171          28 :     return;
     172             :   }
     173             : 
     174             :   char Letter;
     175       28178 :   if (Style == FloatStyle::Exponent)
     176             :     Letter = 'e';
     177         319 :   else if (Style == FloatStyle::ExponentUpper)
     178             :     Letter = 'E';
     179             :   else
     180         304 :     Letter = 'f';
     181             : 
     182       56356 :   SmallString<8> Spec;
     183       56356 :   llvm::raw_svector_ostream Out(Spec);
     184       56356 :   Out << "%." << Prec << Letter;
     185             : 
     186             :   if (Style == FloatStyle::Exponent || Style == FloatStyle::ExponentUpper) {
     187             : #ifdef _WIN32
     188             : // On MSVCRT and compatible, output of %e is incompatible to Posix
     189             : // by default. Number of exponent digits should be at least 2. "%+03d"
     190             : // FIXME: Implement our formatter to here or Support/Format.h!
     191             : #if defined(__MINGW32__)
     192             :     // FIXME: It should be generic to C++11.
     193             :     if (N == 0.0 && std::signbit(N)) {
     194             :       char NegativeZero[] = "-0.000000e+00";
     195             :       if (Style == FloatStyle::ExponentUpper)
     196             :         NegativeZero[strlen(NegativeZero) - 4] = 'E';
     197             :       S << NegativeZero;
     198             :       return;
     199             :     }
     200             : #else
     201             :     int fpcl = _fpclass(N);
     202             : 
     203             :     // negative zero
     204             :     if (fpcl == _FPCLASS_NZ) {
     205             :       char NegativeZero[] = "-0.000000e+00";
     206             :       if (Style == FloatStyle::ExponentUpper)
     207             :         NegativeZero[strlen(NegativeZero) - 4] = 'E';
     208             :       S << NegativeZero;
     209             :       return;
     210             :     }
     211             : #endif
     212             : 
     213             :     char buf[32];
     214             :     unsigned len;
     215             :     len = format(Spec.c_str(), N).snprint(buf, sizeof(buf));
     216             :     if (len <= sizeof(buf) - 2) {
     217             :       if (len >= 5 && (buf[len - 5] == 'e' || buf[len - 5] == 'E') &&
     218             :           buf[len - 3] == '0') {
     219             :         int cs = buf[len - 4];
     220             :         if (cs == '+' || cs == '-') {
     221             :           int c1 = buf[len - 2];
     222             :           int c0 = buf[len - 1];
     223             :           if (isdigit(static_cast<unsigned char>(c1)) &&
     224             :               isdigit(static_cast<unsigned char>(c0))) {
     225             :             // Trim leading '0': "...e+012" -> "...e+12\0"
     226             :             buf[len - 3] = c1;
     227             :             buf[len - 2] = c0;
     228             :             buf[--len] = 0;
     229             :           }
     230             :         }
     231             :       }
     232             :       S << buf;
     233             :       return;
     234             :     }
     235             : #endif
     236             :   }
     237             : 
     238       28178 :   if (Style == FloatStyle::Percent)
     239          56 :     N *= 100.0;
     240             : 
     241             :   char Buf[32];
     242       84534 :   format(Spec.c_str(), N).snprint(Buf, sizeof(Buf));
     243       28178 :   S << Buf;
     244       28178 :   if (Style == FloatStyle::Percent)
     245             :     S << '%';
     246             : }
     247             : 
     248        2376 : bool llvm::isPrefixedHexStyle(HexPrintStyle S) {
     249        2376 :   return (S == HexPrintStyle::PrefixLower || S == HexPrintStyle::PrefixUpper);
     250             : }
     251             : 
     252       29021 : size_t llvm::getDefaultPrecision(FloatStyle Style) {
     253       29021 :   switch (Style) {
     254             :   case FloatStyle::Exponent:
     255             :   case FloatStyle::ExponentUpper:
     256             :     return 6; // Number of decimal places.
     257         463 :   case FloatStyle::Fixed:
     258             :   case FloatStyle::Percent:
     259         463 :     return 2; // Number of decimal places.
     260             :   }
     261           0 :   LLVM_BUILTIN_UNREACHABLE;
     262             : }

Generated by: LCOV version 1.13