From 16dfdeefc8469c9bb8770bab763fd943b62f875d Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 16 Aug 2017 16:04:08 -0700 Subject: [PATCH] spirv: Rework logging MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Ian Romanick --- src/compiler/spirv/nir_spirv.h | 14 +++++ src/compiler/spirv/spirv2nir.c | 5 +- src/compiler/spirv/spirv_to_nir.c | 98 +++++++++++++++++++++++++++---- src/compiler/spirv/vtn_private.h | 20 +++++-- 4 files changed, 119 insertions(+), 18 deletions(-) diff --git a/src/compiler/spirv/nir_spirv.h b/src/compiler/spirv/nir_spirv.h index 234b0ce3444..f129a205764 100644 --- a/src/compiler/spirv/nir_spirv.h +++ b/src/compiler/spirv/nir_spirv.h @@ -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, diff --git a/src/compiler/spirv/spirv2nir.c b/src/compiler/spirv/spirv2nir.c index 0ae14fb19b1..5957f064b49 100644 --- a/src/compiler/spirv/spirv2nir.c +++ b/src/compiler/spirv/spirv2nir.c @@ -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; diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 46ba005945d..a918985daab 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -31,29 +31,89 @@ #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; diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index b4380294048..cac4d45864b 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -37,6 +37,18 @@ 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, -- 2.30.2