printf: extract clovers printf impl
authorKarol Herbst <kherbst@redhat.com>
Sat, 16 Apr 2022 08:48:08 +0000 (10:48 +0200)
committerMarge Bot <emma+marge@anholt.net>
Thu, 4 Aug 2022 23:53:49 +0000 (23:53 +0000)
Also make the code cleaner and simplier.

Signed-off-by: Karol Herbst <kherbst@redhat.com>
Acked-by: Jesse Natalie <jenatali@microsoft.com>
Reviewed-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17334>

src/compiler/nir/nir.h
src/compiler/spirv/vtn_opencl.c
src/gallium/frontends/clover/core/binary.hpp
src/gallium/frontends/clover/core/printf.cpp
src/gallium/frontends/clover/nir/invocation.cpp
src/util/u_printf.c
src/util/u_printf.h

index 89b9c79..85c40db 100644 (file)
@@ -39,6 +39,7 @@
 #include "util/compiler.h"
 #include "util/enum_operators.h"
 #include "util/macros.h"
+#include "util/u_printf.h"
 #include "util/format/u_format.h"
 #include "compiler/nir_types.h"
 #include "compiler/shader_enums.h"
@@ -3157,13 +3158,6 @@ typedef struct {
    uint8_t bit_size;
 } nir_parameter;
 
-typedef struct nir_printf_info {
-   unsigned num_args;
-   unsigned *arg_sizes;
-   unsigned string_size;
-   char *strings;
-} nir_printf_info;
-
 typedef struct nir_function {
    struct exec_node node;
 
@@ -3732,7 +3726,7 @@ typedef struct nir_shader {
    struct nir_xfb_info *xfb_info;
 
    unsigned printf_info_count;
-   nir_printf_info *printf_info;
+   u_printf_info *printf_info;
 } nir_shader;
 
 #define nir_foreach_function(func, shader) \
index befb6ea..0cf715c 100644 (file)
@@ -726,7 +726,7 @@ vtn_handle_opencl_vstore_half_r(struct vtn_builder *b, enum OpenCLstd_Entrypoint
 }
 
 static unsigned
-vtn_add_printf_string(struct vtn_builder *b, uint32_t id, nir_printf_info *info)
+vtn_add_printf_string(struct vtn_builder *b, uint32_t id, u_printf_info *info)
 {
    nir_deref_instr *deref = vtn_nir_deref(b, id);
 
@@ -783,8 +783,8 @@ handle_printf(struct vtn_builder *b, uint32_t opcode,
    unsigned info_idx = b->shader->printf_info_count;
 
    b->shader->printf_info = reralloc(b->shader, b->shader->printf_info,
-                                     nir_printf_info, info_idx);
-   nir_printf_info *info = &b->shader->printf_info[info_idx - 1];
+                                     u_printf_info, info_idx);
+   u_printf_info *info = &b->shader->printf_info[info_idx - 1];
 
    info->strings = NULL;
    info->string_size = 0;
index 951ddc4..a854453 100644 (file)
@@ -57,7 +57,7 @@ namespace clover {
 
       struct printf_info {
          std::vector<uint32_t> arg_sizes;
-         std::vector<uint8_t> strings;
+         std::vector<char> strings;
       };
 
       struct arg_info {
index c6231f1..6a5b7fb 100644 (file)
@@ -40,136 +40,28 @@ namespace {
    const std::string clc_printf_whitelist = "%0123456789-+ #.AacdeEfFgGhilopsuvxX";
 
    void
-   print_formatted(const std::vector<binary::printf_info> &formatters,
+   print_formatted(std::vector<binary::printf_info> &formatters,
                    bool _strings_in_buffer,
                    const std::vector<char> &buffer) {
 
       static std::atomic<unsigned> warn_count;
+
       if (buffer.empty() && !warn_count++)
-        std::cerr << "Printf used but no printf occurred - may cause perfomance issue." << std::endl;
-
-      for (size_t buf_pos = 0; buf_pos < buffer.size(); ) {
-         cl_uint fmt_idx = *(cl_uint*)&buffer[buf_pos];
-         assert(fmt_idx > 0);
-         binary::printf_info fmt = formatters[fmt_idx-1];
-
-         std::string format = (char *)fmt.strings.data();
-         buf_pos += sizeof(cl_uint);
-
-         if (fmt.arg_sizes.empty()) {
-            printf("%s", format.c_str());
-
-         } else {
-            size_t fmt_last_pos = 0;
-            size_t fmt_pos = 0;
-            for (int arg_size : fmt.arg_sizes) {
-               const size_t spec_pos = util_printf_next_spec_pos(format.c_str(), fmt_pos);
-               const size_t cur_tok = format.rfind('%', spec_pos);
-               const size_t next_spec = util_printf_next_spec_pos(format.c_str(), spec_pos);
-               const size_t next_tok = next_spec == std::string::npos ? std::string::npos :
-                  format.rfind('%', next_spec);
-
-               size_t vec_pos = format.find_first_of("v", cur_tok + 1);
-               size_t mod_pos = format.find_first_of("hl", cur_tok + 1);
-
-               // print the part before the format token
-               if (cur_tok != fmt_last_pos) {
-                  std::string s = format.substr(fmt_last_pos,
-                                                cur_tok - fmt_last_pos);
-                  printf("%s", s.c_str());
-               }
-
-               std::string print_str;
-               print_str = format.substr(cur_tok, spec_pos + 1 - cur_tok);
-
-               /* Never pass a 'n' spec to the host printf */
-               bool valid_str = print_str.find_first_not_of(clc_printf_whitelist) ==
-                  std::string::npos;
-
-               // print the formated part
-               if (spec_pos != std::string::npos && valid_str) {
-                  bool is_vector = vec_pos != std::string::npos &&
-                     vec_pos + 1 < spec_pos;
-                  bool is_string = format[spec_pos] == 's';
-                  bool is_float = std::string("fFeEgGaA")
-                     .find(format[spec_pos]) != std::string::npos;
-
-                  if (is_string) {
-                     if (_strings_in_buffer)
-                        printf(print_str.c_str(), &buffer[buf_pos]);
-                     else {
-                        uint64_t idx;
-                        memcpy(&idx, &buffer[buf_pos], 8);
-                        printf(print_str.c_str(), &fmt.strings[idx]);
-                     }
-                  } else {
-                     int component_count = 1;
-
-                     if (is_vector) {
-                        size_t l = std::min(mod_pos, spec_pos) - vec_pos - 1;
-                        std::string s = format.substr(vec_pos + 1, l);
-                        component_count = std::stoi(s);
-                        if (mod_pos != std::string::npos) {
-                           // CL C has hl specifier for 32-bit vectors, C doesn't have it
-                           // just remove it.
-                           std::string mod = format.substr(mod_pos, 2);
-                           if (mod == "hl")
-                              mod_pos = std::string::npos;
-                       }
-                        print_str.erase(vec_pos - cur_tok, std::min(mod_pos, spec_pos) - vec_pos);
-                        print_str.push_back(',');
-                     }
-
-                     //in fact vec3 are vec4
-                     int men_components =
-                        component_count == 3 ? 4 : component_count;
-                     size_t elmt_size = arg_size / men_components;
-
-                     for (int i = 0; i < component_count; i++) {
-                        size_t elmt_buf_pos = buf_pos + i * elmt_size;
-                        if (is_vector && i + 1 == component_count)
-                           print_str.pop_back();
-
-                        if (is_float) {
-                           switch (elmt_size) {
-                           case 2:
-                              cl_half h;
-                              std::memcpy(&h, &buffer[elmt_buf_pos], elmt_size);
-                              printf(print_str.c_str(), h);
-                              break;
-                           case 4:
-                              cl_float f;
-                              std::memcpy(&f, &buffer[elmt_buf_pos], elmt_size);
-                              printf(print_str.c_str(), f);
-                              break;
-                           default:
-                              cl_double d;
-                              std::memcpy(&d, &buffer[elmt_buf_pos], elmt_size);
-                              printf(print_str.c_str(), d);
-                           }
-                        } else {
-                           cl_long l = 0;
-                           std::memcpy(&l, &buffer[elmt_buf_pos], elmt_size);
-                           printf(print_str.c_str(), l);
-                        }
-                     }
-                  }
-                  // print the remaining
-                  if (next_tok != spec_pos) {
-                     std::string s = format.substr(spec_pos + 1,
-                                                   next_tok - spec_pos - 1);
-                     printf("%s", s.c_str());
-                  }
-               }
-
-               fmt_pos = spec_pos;
-               fmt_last_pos = next_tok;
-
-               buf_pos += arg_size;
-               buf_pos = ALIGN(buf_pos, 4);
-            }
-         }
+         std::cerr << "Printf used but no printf occurred - may cause perfomance issue." << std::endl;
+
+      std::vector<u_printf_info> infos;
+      for (auto &f : formatters) {
+         u_printf_info info;
+
+         info.num_args = f.arg_sizes.size();
+         info.arg_sizes = f.arg_sizes.data();
+         info.string_size = f.strings.size();
+         info.strings = f.strings.data();
+
+         infos.push_back(info);
       }
+
+      u_printf(stdout, buffer.data(), buffer.size(), infos.data(), infos.size());
    }
 }
 
index b741a0a..e84123d 100644 (file)
@@ -588,7 +588,7 @@ binary clover::nir::spirv_to_nir(const binary &mod, const device &dev,
 
       void *mem_ctx = ralloc_context(NULL);
       unsigned printf_info_count = nir->printf_info_count;
-      nir_printf_info *printf_infos = nir->printf_info;
+      u_printf_info *printf_infos = nir->printf_info;
 
       ralloc_steal(mem_ctx, printf_infos);
 
index ff57998..b4ea39d 100644 (file)
 
 #include <assert.h>
 #include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "macros.h"
+#include "strndup.h"
+#include "u_math.h"
 #include "u_printf.h"
 
 /* Some versions of MinGW are missing _vscprintf's declaration, although they
@@ -42,6 +46,14 @@ _CRTIMP int _vscprintf(const char *format, va_list argptr);
 #endif
 #endif
 
+static const char*
+util_printf_prev_tok(const char *str)
+{
+   while (*str != '%')
+      str--;
+   return str;
+}
+
 size_t util_printf_next_spec_pos(const char *str, size_t pos)
 {
    if (str == NULL)
@@ -94,3 +106,137 @@ size_t u_printf_length(const char *fmt, va_list untouched_args)
 
    return size;
 }
+
+void u_printf(FILE *out, const char *buffer, size_t buffer_size,
+              const u_printf_info *info, unsigned info_size)
+{
+   for (size_t buf_pos = 0; buf_pos < buffer_size;) {
+      uint32_t fmt_idx = *(uint32_t*)&buffer[buf_pos];
+
+      /* the idx is 1 based */
+      assert(fmt_idx > 0);
+      fmt_idx -= 1;
+
+      /* The API allows more arguments than the format uses */
+      if (fmt_idx >= info_size)
+         return;
+
+      const u_printf_info *fmt = &info[fmt_idx];
+      const char *format = fmt->strings;
+      buf_pos += sizeof(fmt_idx);
+
+      if (!fmt->num_args) {
+         fprintf(out, "%s", format);
+         continue;
+      }
+
+      for (int i = 0; i < fmt->num_args; i++) {
+         int arg_size = fmt->arg_sizes[i];
+         size_t spec_pos = util_printf_next_spec_pos(format, 0);
+
+         if (spec_pos == -1) {
+            fprintf(out, "%s", format);
+            continue;
+         }
+
+         const char *token = util_printf_prev_tok(&format[spec_pos]);
+         const char *next_format = &format[spec_pos + 1];
+
+         /* print the part before the format token */
+         if (token != format)
+            fwrite(format, token - format, 1, out);
+
+         char *print_str = strndup(token, next_format - token);
+         /* rebase spec_pos so we can use it with print_str */
+         spec_pos += format - token;
+
+         /* print the formated part */
+         if (print_str[spec_pos] == 's') {
+            uint64_t idx;
+            memcpy(&idx, &buffer[buf_pos], 8);
+            fprintf(out, print_str, &fmt->strings[idx]);
+
+         /* Never pass a 'n' spec to the host printf */
+         } else if (print_str[spec_pos] != 'n') {
+            char *vec_pos = strchr(print_str, 'v');
+            char *mod_pos = strpbrk(print_str, "hl");
+
+            int component_count = 1;
+            if (vec_pos != NULL) {
+               /* non vector part of the format */
+               size_t base = mod_pos ? mod_pos - print_str : spec_pos;
+               size_t l = base - (vec_pos - print_str) - 1;
+               char *vec = strndup(&vec_pos[1], l);
+               component_count = atoi(vec);
+               free(vec);
+
+               /* remove the vector and precision stuff */
+               memmove(&print_str[vec_pos - print_str], &print_str[spec_pos], 2);
+            }
+
+            /* in fact vec3 are vec4 */
+            int men_components = component_count == 3 ? 4 : component_count;
+            size_t elmt_size = arg_size / men_components;
+            bool is_float = strpbrk(print_str, "fFeEgGaA") != NULL;
+
+            for (int i = 0; i < component_count; i++) {
+               size_t elmt_buf_pos = buf_pos + i * elmt_size;
+               switch (elmt_size) {
+               case 1: {
+                  uint8_t v;
+                  memcpy(&v, &buffer[elmt_buf_pos], elmt_size);
+                  fprintf(out, print_str, v);
+                  break;
+               }
+               case 2: {
+                  uint16_t v;
+                  memcpy(&v, &buffer[elmt_buf_pos], elmt_size);
+                  fprintf(out, print_str, v);
+                  break;
+               }
+               case 4: {
+                  if (is_float) {
+                     float v;
+                     memcpy(&v, &buffer[elmt_buf_pos], elmt_size);
+                     fprintf(out, print_str, v);
+                  } else {
+                     uint32_t v;
+                     memcpy(&v, &buffer[elmt_buf_pos], elmt_size);
+                     fprintf(out, print_str, v);
+                  }
+                  break;
+               }
+               case 8: {
+                  if (is_float) {
+                     double v;
+                     memcpy(&v, &buffer[elmt_buf_pos], elmt_size);
+                     fprintf(out, print_str, v);
+                  } else {
+                     uint64_t v;
+                     memcpy(&v, &buffer[elmt_buf_pos], elmt_size);
+                     fprintf(out, print_str, v);
+                  }
+                  break;
+               }
+               default:
+                  assert(false);
+                  break;
+               }
+
+               if (i < component_count - 1)
+                  fprintf(out, ",");
+            }
+         }
+
+         /* rebase format */
+         format = next_format;
+         free(print_str);
+
+         buf_pos += arg_size;
+         buf_pos = ALIGN(buf_pos, 4);
+      }
+
+      /* print remaining */
+      fprintf(out, "%s", format);
+   }
+}
index 63c212e..d0f6b4d 100644 (file)
 extern "C" {
 #endif
 
+typedef struct u_printf_info {
+   unsigned num_args;
+   unsigned *arg_sizes;
+   unsigned string_size;
+   char *strings;
+} u_printf_info;
+
 /* find next valid printf specifier in a C string wrapper */
 size_t util_printf_next_spec_pos(const char *str, size_t pos);
 
@@ -39,6 +46,9 @@ size_t util_printf_next_spec_pos(const char *str, size_t pos);
  */
 size_t u_printf_length(const char *fmt, va_list untouched_args);
 
+void u_printf(FILE *out, const char *buffer, size_t buffer_size,
+              const u_printf_info*, unsigned info_size);
+
 #ifdef __cplusplus
 }
 #endif