spirv: Rework logging

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>
This commit is contained in:
Jason Ekstrand 2017-08-16 16:04:08 -07:00
parent 11bd753c4e
commit 16dfdeefc8
4 changed files with 121 additions and 20 deletions

View 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,

View 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;

View file

@ -31,6 +31,81 @@
#include "nir/nir_constant_expressions.h"
#include "spirv_info.h"
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_logf(struct vtn_builder *b, enum nir_spirv_debug_level level,
size_t spirv_offset, const char *fmt, ...)
{
va_list args;
char *msg;
va_start(args, fmt);
msg = ralloc_vasprintf(NULL, fmt, args);
va_end(args);
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(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 {
@ -39,21 +114,6 @@ struct spec_constant_value {
};
};
void
_vtn_warn(const char *file, int line, const char *msg, ...)
{
char *formatted;
va_list args;
va_start(args, msg);
formatted = ralloc_vasprintf(NULL, msg, args);
va_end(args);
fprintf(stderr, "%s:%d WARNING: %s\n", file, line, formatted);
ralloc_free(formatted);
}
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;

View file

@ -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,