github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/native/test/xprintf.h (about)

     1  /*
     2   * Copyright 2022 ByteDance Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  #pragma once
    18  
    19  #include <sys/types.h>
    20  
    21  #ifdef LOG_LEVEL
    22  #define DEBUG
    23  #define LOG_TRACE(_VA_ARGS__...) do { if (LOG_LEVEL >= 0) xprintf(_VA_ARGS__ ); } while (0)
    24  #define LOG_DEBUG(_VA_ARGS__...) do { if (LOG_LEVEL >= 1) xprintf(_VA_ARGS__ ); } while (0)
    25  #define LOG_INFO(_VA_ARGS__...)  do { if (LOG_LEVEL >= 2) xprintf(_VA_ARGS__ ); } while (0)
    26  #else
    27  #define LOG_TRACE(_VA_ARGS__...) ((void)0)
    28  #define LOG_DEBUG(_VA_ARGS__...) ((void)0)
    29  #define LOG_INFO(_VA_ARGS__...)  ((void)0)
    30  #endif
    31  
    32  // Note: this code is on cross-compile, so we can't use System-specific Predefined Macros here.
    33  #if USE_APPLE
    34  static inline void __attribute__((naked)) write_syscall(const char *s, size_t n)
    35  {
    36      asm volatile(
    37          "movq %rsi, %rdx"
    38          "\n"
    39          "movq %rdi, %rsi"
    40          "\n"
    41          "movq $1, %rdi"
    42          "\n"
    43          "movq $0x02000004, %rax"
    44          "\n"
    45          "syscall"
    46          "\n"
    47          "retq"
    48          "\n");
    49  }
    50  #else
    51  static inline void __attribute__((naked)) write_syscall(const char *s, size_t n)
    52  {
    53      asm volatile(
    54          "movq %rsi, %rdx"
    55          "\n"
    56          "movq %rdi, %rsi"
    57          "\n"
    58          "movq $1, %rdi"
    59          "\n"
    60          "movq $1, %rax"
    61          "\n"
    62          "syscall"
    63          "\n"
    64          "retq"
    65          "\n");
    66  }
    67  #endif
    68  
    69  static inline void printch(const char ch)
    70  {
    71      write_syscall(&ch, 1);
    72  }
    73  
    74  static inline void printstr(const char *s)
    75  {
    76      size_t n = 0;
    77      const char *p = s;
    78      while (*p++)
    79          n++;
    80      write_syscall(s, n);
    81  }
    82  
    83  static inline void printint(int64_t v)
    84  {
    85      char neg = 0;
    86      char buf[32] = {};
    87      char *p = &buf[31];
    88      uint64_t u;
    89      if (v < 0) {
    90          u = ~v + 1;
    91          neg = 1;
    92      } else {
    93          u = v;
    94      }
    95      if (u == 0) {
    96          *--p = '0';
    97          goto sig;
    98      }
    99      while (u)
   100      {
   101          *--p = (u % 10) + '0';
   102          u /= 10;
   103      }
   104  sig:
   105      if (neg) {
   106          *--p = '-';
   107      }
   108      printstr(p);
   109  }
   110  
   111  static inline void printuint(uint64_t v)
   112  {
   113      char buf[32] = {};
   114      char *p = &buf[31];
   115      if (v == 0)
   116      {
   117          printch('0');
   118          return;
   119      }
   120      while (v)
   121      {
   122          *--p = (v % 10) + '0';
   123          v /= 10;
   124      }
   125      printstr(p);
   126  }
   127  
   128  static const char tab[] = "0123456789abcdef";
   129  
   130  static inline void printhex(uintptr_t v)
   131  {
   132      if (v == 0)
   133      {
   134          printch('0');
   135          return;
   136      }
   137      char buf[32] = {};
   138      char *p = &buf[31];
   139  
   140      while (v)
   141      {
   142          *--p = tab[v & 0x0f];
   143          v >>= 4;
   144      }
   145      printstr(p);
   146  }
   147  
   148  #define MAX_BUF_LEN 1000
   149  
   150  static inline void printbytes(GoSlice *s)
   151  {
   152      printch('[');
   153      int i = 0;
   154      if (s->len > MAX_BUF_LEN)
   155      {
   156          i = s->len - MAX_BUF_LEN;
   157      }
   158      for (; i < s->len; i++)
   159      {
   160          char* bytes = (char*)(s->buf);
   161          printch(tab[(bytes[i] & 0xf0) >> 4]);
   162          printch(tab[bytes[i] & 0x0f]);
   163          if (i != s->len - 1)
   164              printch(',');
   165      }
   166      printch(']');
   167  }
   168  
   169  static inline void printgostr(GoString *s)
   170  {
   171      printch('"');
   172      if (s->len < MAX_BUF_LEN)
   173      {
   174          write_syscall(s->buf, s->len);
   175      }
   176      else
   177      {
   178          write_syscall(s->buf, MAX_BUF_LEN);
   179      }
   180      printch('"');
   181  }
   182  
   183  static inline void do_xprintf(const char *fmt, ...)
   184  {
   185      __builtin_va_list va;
   186      char buf[256] = {};
   187      char *p = buf;
   188      __builtin_va_start(va, fmt);
   189      for (;;)
   190      {
   191          if (*fmt == 0)
   192          {
   193              break;
   194          }
   195          if (*fmt != '%')
   196          {
   197              *p++ = *fmt++;
   198              continue;
   199          }
   200          *p = 0;
   201          p = buf;
   202          fmt++;
   203          printstr(buf);
   204          switch (*fmt++)
   205          {
   206          case '%':
   207          {
   208              printch('%');
   209              break;
   210          }
   211          case 'g':
   212          {
   213              printgostr(__builtin_va_arg(va, GoString *));
   214              break;
   215          }
   216          case 's':
   217          {
   218              printstr(__builtin_va_arg(va, const char *));
   219              break;
   220          }
   221          case 'd':
   222          {
   223              printint(__builtin_va_arg(va, int64_t));
   224              break;
   225          }
   226          case 'u':
   227          {
   228              printuint(__builtin_va_arg(va, uint64_t));
   229              break;
   230          }
   231          case 'f':
   232          {
   233              printint(__builtin_va_arg(va, double));
   234              break;
   235          }
   236          case 'c':
   237          {
   238              printch((char)(__builtin_va_arg(va, int)));
   239              break;
   240          }
   241          case 'x':
   242          {
   243              printhex(__builtin_va_arg(va, uintptr_t));
   244              break;
   245          }
   246          case 'l':
   247          {
   248              printbytes(__builtin_va_arg(va, GoSlice *));
   249              break;
   250          }
   251          }
   252      }
   253      __builtin_va_end(va);
   254      if (p != buf)
   255      {
   256          *p = 0;
   257          printstr(buf);
   258      }
   259  }
   260  
   261  #ifdef DEBUG
   262  #define xprintf(_VA_ARGS__...)  do_xprintf(_VA_ARGS__)
   263  #else
   264  #define xprintf(_VA_ARGS__...)  ((void)0)
   265  #endif
   266  
   267  static always_inline void print_longhex(const void *input, const char* s, int bytes) {
   268      const uint8_t* p = (const uint8_t*)(input);
   269      xprintf("%s : ", s);
   270      for (int i = 0; i < bytes; i++) {
   271          uintptr_t u = p[i];
   272          if (u < 0x10) xprintf("0");
   273          xprintf("%x", u);
   274          if ((i + 1) < bytes && (i + 1) % 4 == 0) {
   275              xprintf("-");
   276          }
   277      }
   278      xprintf("\n");
   279  }
   280  
   281  #define psimd(simd) print_longhex((const void *)(simd), #simd, sizeof(*simd))