LCOV - code coverage report
Current view: top level - lib/Support - NativeFormatting.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 143 146 97.9 %
Date: 2018-10-20 13:21:21 Functions: 19 19 100.0 %
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   248081184 :   do {
      27   248081184 :     *--CurPtr = '0' + char(Value % 10);
      28   248081184 :     Value /= 10;
      29             :   } while (Value);
      30   112733970 :   return EndPtr - CurPtr;
      31             : }
      32             : 
      33          92 : static void writeWithCommas(raw_ostream &S, ArrayRef<char> Buffer) {
      34             :   assert(!Buffer.empty());
      35             : 
      36             :   ArrayRef<char> ThisGroup;
      37          92 :   int InitialDigits = ((Buffer.size() - 1) % 3) + 1;
      38          92 :   ThisGroup = Buffer.take_front(InitialDigits);
      39          92 :   S.write(ThisGroup.data(), ThisGroup.size());
      40             : 
      41             :   Buffer = Buffer.drop_front(InitialDigits);
      42             :   assert(Buffer.size() % 3 == 0);
      43         135 :   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          92 : }
      50             : 
      51             : template <typename T>
      52   112733970 : 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   112733970 :   std::memset(NumberBuffer, '0', sizeof(NumberBuffer));
      58             : 
      59             :   size_t Len = 0;
      60   112733970 :   Len = format_to_buffer(N, NumberBuffer);
      61             : 
      62   112733970 :   if (IsNegative)
      63             :     S << '-';
      64             : 
      65   112733970 :   if (Len < MinDigits && Style != IntegerStyle::Number) {
      66        2143 :     for (size_t I = Len; I < MinDigits; ++I)
      67             :       S << '0';
      68             :   }
      69             : 
      70   112733971 :   if (Style == IntegerStyle::Number) {
      71         184 :     writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len));
      72             :   } else {
      73   112733879 :     S.write(std::end(NumberBuffer) - Len, Len);
      74             :   }
      75   112733971 : }
      76           4 : 
      77             : template <typename T>
      78             : 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           4 :   if (N == static_cast<uint32_t>(N))
      82             :     write_unsigned_impl(S, static_cast<uint32_t>(N), MinDigits, Style,
      83             :                         IsNegative);
      84           4 :   else
      85             :     write_unsigned_impl(S, N, MinDigits, Style, IsNegative);
      86           4 : }
      87             : 
      88             : template <typename T>
      89           4 : static void write_signed(raw_ostream &S, T N, size_t MinDigits,
      90           0 :                          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           4 : 
      95           4 :   if (N >= 0) {
      96             :     write_unsigned(S, static_cast<UnsignedT>(N), MinDigits, Style);
      97           2 :     return;
      98             :   }
      99           4 : 
     100       34573 :   UnsignedT UN = -(UnsignedT)N;
     101             :   write_unsigned(S, UN, MinDigits, Style, true);
     102             : }
     103             : 
     104             : void llvm::write_integer(raw_ostream &S, unsigned int N, size_t MinDigits,
     105       34573 :                          IntegerStyle Style) {
     106             :   write_unsigned(S, N, MinDigits, Style);
     107             : }
     108       34573 : 
     109             : void llvm::write_integer(raw_ostream &S, int N, size_t MinDigits,
     110       34573 :                          IntegerStyle Style) {
     111             :   write_signed(S, N, MinDigits, Style);
     112             : }
     113       34573 : 
     114           0 : void llvm::write_integer(raw_ostream &S, unsigned long N, size_t MinDigits,
     115             :                          IntegerStyle Style) {
     116             :   write_unsigned(S, N, MinDigits, Style);
     117             : }
     118       34573 : 
     119           4 : void llvm::write_integer(raw_ostream &S, long N, size_t MinDigits,
     120             :                          IntegerStyle Style) {
     121       34571 :   write_signed(S, N, MinDigits, Style);
     122             : }
     123       34573 : 
     124   112699393 : void llvm::write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits,
     125             :                          IntegerStyle Style) {
     126             :   write_unsigned(S, N, MinDigits, Style);
     127             : }
     128             : 
     129   112699393 : void llvm::write_integer(raw_ostream &S, long long N, size_t MinDigits,
     130             :                          IntegerStyle Style) {
     131             :   write_signed(S, N, MinDigits, Style);
     132   112699393 : }
     133             : 
     134   112699393 : void llvm::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
     135             :                      Optional<size_t> Width) {
     136             :   const size_t kMaxWidth = 128u;
     137   112699393 : 
     138        2143 :   size_t W = std::min(kMaxWidth, Width.getValueOr(0u));
     139             : 
     140             :   unsigned Nibbles = (64 - countLeadingZeros(N) + 3) / 4;
     141             :   bool Prefix = (Style == HexPrintStyle::PrefixLower ||
     142   112699394 :                  Style == HexPrintStyle::PrefixUpper);
     143         176 :   bool Upper =
     144             :       (Style == HexPrintStyle::Upper || Style == HexPrintStyle::PrefixUpper);
     145   112699306 :   unsigned PrefixChars = Prefix ? 2 : 0;
     146             :   unsigned NumChars =
     147   112699394 :       std::max(static_cast<unsigned>(W), std::max(1u, Nibbles) + PrefixChars);
     148             : 
     149             :   char NumberBuffer[kMaxWidth];
     150   112721678 :   ::memset(NumberBuffer, '0', llvm::array_lengthof(NumberBuffer));
     151             :   if (Prefix)
     152             :     NumberBuffer[1] = 'x';
     153   112721678 :   char *EndPtr = NumberBuffer + NumChars;
     154   112699393 :   char *CurPtr = EndPtr;
     155             :   while (N) {
     156             :     unsigned char x = static_cast<unsigned char>(N) % 16;
     157       34577 :     *--CurPtr = hexdigit(x, !Upper);
     158   112721679 :     N /= 16;
     159          62 :   }
     160             : 
     161             :   S.write(NumberBuffer, NumChars);
     162          62 : }
     163          58 : 
     164             : void llvm::write_double(raw_ostream &S, double N, FloatStyle Style,
     165             :                         Optional<size_t> Precision) {
     166           4 :   size_t Prec = Precision.getValueOr(getDefaultPrecision(Style));
     167          62 : 
     168   112721616 :   if (std::isnan(N)) {
     169             :     S << "nan";
     170             :     return;
     171   112721616 :   } else if (std::isinf(N)) {
     172   112687043 :     S << "INF";
     173             :     return;
     174             :   }
     175       34573 : 
     176   112721617 :   char Letter;
     177             :   if (Style == FloatStyle::Exponent)
     178             :     Letter = 'e';
     179    35670210 :   else if (Style == FloatStyle::ExponentUpper)
     180             :     Letter = 'E';
     181             :   else
     182             :     Letter = 'f';
     183             : 
     184             :   SmallString<8> Spec;
     185    35670210 :   llvm::raw_svector_ostream Out(Spec);
     186    34571209 :   Out << "%." << Prec << Letter;
     187    34571209 : 
     188             :   if (Style == FloatStyle::Exponent || Style == FloatStyle::ExponentUpper) {
     189             : #ifdef _WIN32
     190     1099001 : // On MSVCRT and compatible, output of %e is incompatible to Posix
     191     1098688 : // by default. Number of exponent digits should be at least 2. "%+03d"
     192             : // FIXME: Implement our formatter to here or Support/Format.h!
     193          57 : #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          57 :       S << NegativeZero;
     200          55 :       return;
     201          55 :     }
     202             : #else
     203             :     int fpcl = _fpclass(N);
     204           2 : 
     205           2 :     // negative zero
     206             :     if (fpcl == _FPCLASS_NZ) {
     207    35664929 :       char NegativeZero[] = "-0.000000e+00";
     208             :       if (Style == FloatStyle::ExponentUpper)
     209             :         NegativeZero[strlen(NegativeZero) - 4] = 'E';
     210             :       S << NegativeZero;
     211             :       return;
     212             :     }
     213    35664929 : #endif
     214    34566243 : 
     215    34566243 :     char buf[32];
     216             :     unsigned len;
     217             :     len = format(Spec.c_str(), N).snprint(buf, sizeof(buf));
     218     1098686 :     if (len <= sizeof(buf) - 2) {
     219     1098686 :       if (len >= 5 && (buf[len - 5] == 'e' || buf[len - 5] == 'E') &&
     220             :           buf[len - 3] == '0') {
     221        5224 :         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        5224 :             // Trim leading '0': "...e+012" -> "...e+12\0"
     228        4911 :             buf[len - 3] = c1;
     229        4911 :             buf[len - 2] = c0;
     230             :             buf[--len] = 0;
     231             :           }
     232         313 :         }
     233             :       }
     234             :       S << buf;
     235             :       return;
     236        7068 :     }
     237             : #endif
     238             :   }
     239        7068 : 
     240             :   if (Style == FloatStyle::Percent)
     241        5224 :     N *= 100.0;
     242             : 
     243        5224 :   char Buf[32];
     244        5224 :   format(Spec.c_str(), N).snprint(Buf, sizeof(Buf));
     245             :   S << Buf;
     246    77056689 :   if (Style == FloatStyle::Percent)
     247             :     S << '%';
     248    77056689 : }
     249    77056689 : 
     250             : bool llvm::isPrefixedHexStyle(HexPrintStyle S) {
     251    35664929 :   return (S == HexPrintStyle::PrefixLower || S == HexPrintStyle::PrefixUpper);
     252             : }
     253    35664929 : 
     254    35664929 : size_t llvm::getDefaultPrecision(FloatStyle Style) {
     255             :   switch (Style) {
     256           5 :   case FloatStyle::Exponent:
     257             :   case FloatStyle::ExponentUpper:
     258           5 :     return 6; // Number of decimal places.
     259           5 :   case FloatStyle::Fixed:
     260             :   case FloatStyle::Percent:
     261          57 :     return 2; // Number of decimal places.
     262             :   }
     263          57 :   LLVM_BUILTIN_UNREACHABLE;
     264          57 : }

Generated by: LCOV version 1.13