spirv: Rework logging
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 16 Aug 2017 23:04:08 +0000 (16:04 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Mon, 4 Dec 2017 17:21:09 +0000 (09:21 -0800)
This commit reworks the way that logging works in SPIR-V to provide
richer and more detailed logging infrastructure.  This commit contains
several improvements over the old mechanism:

 1) Log messages are now more detailed.  They contain the SPIR-V byte
    offset as well as source language information from OpSource and
    OpLine.

 2) There is now a logging callback mechanism so that errors can get
    propagated to the client through debug callbak extensions.

Reviewed-by: Tapani Pälli <tapani.palli@intel.com>
Reviewed-by: Ian Romanick <idr@freedesktop.org>
src/compiler/spirv/nir_spirv.h
src/compiler/spirv/spirv2nir.c
src/compiler/spirv/spirv_to_nir.c
src/compiler/spirv/vtn_private.h

index 234b0ce344469018a558af54aecbd4c4a106e0af..f129a205764a683ae897ed0669f9fd0e4ace5221 100644 (file)
@@ -42,6 +42,12 @@ struct nir_spirv_specialization {
    };
 };
 
+enum nir_spirv_debug_level {
+   NIR_SPIRV_DEBUG_LEVEL_INFO,
+   NIR_SPIRV_DEBUG_LEVEL_WARNING,
+   NIR_SPIRV_DEBUG_LEVEL_ERROR,
+};
+
 struct spirv_to_nir_options {
    struct {
       bool float64;
@@ -54,6 +60,14 @@ struct spirv_to_nir_options {
       bool multiview;
       bool variable_pointers;
    } caps;
+
+   struct {
+      void (*func)(void *private_data,
+                   enum nir_spirv_debug_level level,
+                   size_t spirv_offset,
+                   const char *message);
+      void *private_data;
+   } debug;
 };
 
 nir_function *spirv_to_nir(const uint32_t *words, size_t word_count,
index 0ae14fb19b1fca8ff5fc46411c2cbc4008d0d6fd..5957f064b49c1c9ee79007f46339051c008c47b2 100644 (file)
@@ -72,8 +72,11 @@ int main(int argc, char **argv)
       return 1;
    }
 
+   struct spirv_to_nir_options spirv_opts = {};
+
    nir_function *func = spirv_to_nir(map, word_count, NULL, 0,
-                                     MESA_SHADER_FRAGMENT, "main", NULL, NULL);
+                                     MESA_SHADER_FRAGMENT, "main",
+                                     &spirv_opts, NULL);
    nir_print_shader(func->shader, stderr);
 
    return 0;
index 46ba005945d99bc4394d75fac6ce5d9c6be6e422..a918985daab11d831d18a645da976148b3d06384 100644 (file)
 #include "nir/nir_constant_expressions.h"
 #include "spirv_info.h"
 
-struct spec_constant_value {
-   bool is_double;
-   union {
-      uint32_t data32;
-      uint64_t data64;
-   };
-};
+void
+vtn_log(struct vtn_builder *b, enum nir_spirv_debug_level level,
+        size_t spirv_offset, const char *message)
+{
+   if (b->options->debug.func) {
+      b->options->debug.func(b->options->debug.private_data,
+                             level, spirv_offset, message);
+   }
+
+#ifndef NDEBUG
+   if (level >= NIR_SPIRV_DEBUG_LEVEL_WARNING)
+      fprintf(stderr, "%s\n", message);
+#endif
+}
 
 void
-_vtn_warn(const char *file, int line, const char *msg, ...)
+vtn_logf(struct vtn_builder *b, enum nir_spirv_debug_level level,
+         size_t spirv_offset, const char *fmt, ...)
 {
-   char *formatted;
    va_list args;
+   char *msg;
 
-   va_start(args, msg);
-   formatted = ralloc_vasprintf(NULL, msg, args);
+   va_start(args, fmt);
+   msg = ralloc_vasprintf(NULL, fmt, args);
    va_end(args);
 
-   fprintf(stderr, "%s:%d WARNING: %s\n", file, line, formatted);
+   vtn_log(b, level, spirv_offset, msg);
+
+   ralloc_free(msg);
+}
+
+static void
+vtn_log_err(struct vtn_builder *b,
+            enum nir_spirv_debug_level level, const char *prefix,
+            const char *file, unsigned line,
+            const char *fmt, va_list args)
+{
+   char *msg;
+
+   msg = ralloc_strdup(NULL, prefix);
+
+#ifndef NDEBUG
+   ralloc_asprintf_append(&msg, "    In file %s:%u\n", file, line);
+#endif
+
+   ralloc_asprintf_append(&msg, "    ");
+
+   ralloc_vasprintf_append(&msg, fmt, args);
+
+   ralloc_asprintf_append(&msg, "\n    %zu bytes into the SPIR-V binary",
+                          b->spirv_offset);
+
+   if (b->file) {
+      ralloc_asprintf_append(&msg,
+                             "\n    in SPIR-V source file %s, line %d, col %d",
+                             b->file, b->line, b->col);
+   }
+
+   vtn_log(b, level, b->spirv_offset, msg);
 
-   ralloc_free(formatted);
+   ralloc_free(msg);
 }
 
+void
+_vtn_warn(struct vtn_builder *b, const char *file, unsigned line,
+          const char *fmt, ...)
+{
+   va_list args;
+
+   va_start(args, fmt);
+   vtn_log_err(b, NIR_SPIRV_DEBUG_LEVEL_WARNING, "SPIR-V WARNING:\n",
+               file, line, fmt, args);
+   va_end(args);
+}
+
+struct spec_constant_value {
+   bool is_double;
+   union {
+      uint32_t data32;
+      uint64_t data64;
+   };
+};
+
 static struct vtn_ssa_value *
 vtn_undef_ssa_value(struct vtn_builder *b, const struct glsl_type *type)
 {
@@ -224,6 +284,8 @@ vtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start,
       unsigned count = w[0] >> SpvWordCountShift;
       assert(count >= 1 && w + count <= end);
 
+      b->spirv_offset = (uint8_t *)w - (uint8_t *)b->spirv;
+
       switch (opcode) {
       case SpvOpNop:
          break; /* Do nothing */
@@ -248,6 +310,12 @@ vtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start,
 
       w += count;
    }
+
+   b->spirv_offset = 0;
+   b->file = NULL;
+   b->line = -1;
+   b->col = -1;
+
    assert(w == end);
    return w;
 }
@@ -3321,6 +3389,10 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
 {
    /* Initialize the stn_builder object */
    struct vtn_builder *b = rzalloc(NULL, struct vtn_builder);
+   b->spirv = words;
+   b->file = NULL;
+   b->line = -1;
+   b->col = -1;
    exec_list_make_empty(&b->functions);
    b->entry_point_stage = stage;
    b->entry_point_name = entry_point_name;
index b43802940485bddec68fe214381b6cde31af6868..cac4d45864b5c8c05e47557958f3a55d4272e205 100644 (file)
 struct vtn_builder;
 struct vtn_decoration;
 
+void vtn_log(struct vtn_builder *b, enum nir_spirv_debug_level level,
+             size_t spirv_offset, const char *message);
+
+void vtn_logf(struct vtn_builder *b, enum nir_spirv_debug_level level,
+              size_t spirv_offset, const char *fmt, ...) PRINTFLIKE(4, 5);
+
+#define vtn_info(...) vtn_logf(b, NIR_SPIRV_DEBUG_LEVEL_INFO, 0, __VA_ARGS__)
+
+void _vtn_warn(struct vtn_builder *b, const char *file, unsigned line,
+               const char *fmt, ...) PRINTFLIKE(4, 5);
+#define vtn_warn(...) _vtn_warn(b, __FILE__, __LINE__, __VA_ARGS__)
+
 enum vtn_value_type {
    vtn_value_type_invalid = 0,
    vtn_value_type_undef,
@@ -466,13 +478,16 @@ struct vtn_decoration {
 struct vtn_builder {
    nir_builder nb;
 
+   const uint32_t *spirv;
+
    nir_shader *shader;
    const struct spirv_to_nir_options *options;
    struct vtn_block *block;
 
-   /* Current file, line, and column.  Useful for debugging.  Set
+   /* Current offset, file, line, and column.  Useful for debugging.  Set
     * automatically by vtn_foreach_instruction.
     */
+   size_t spirv_offset;
    char *file;
    int line, col;
 
@@ -560,9 +575,6 @@ vtn_value(struct vtn_builder *b, uint32_t value_id,
    return val;
 }
 
-void _vtn_warn(const char *file, int line, const char *msg, ...);
-#define vtn_warn(...) _vtn_warn(__FILE__, __LINE__, __VA_ARGS__)
-
 struct vtn_ssa_value *vtn_ssa_value(struct vtn_builder *b, uint32_t value_id);
 
 struct vtn_ssa_value *vtn_create_ssa_value(struct vtn_builder *b,