nir/print: Add a helper for generating debug info

Prints the shader to a string and assigns source locations based on
that.

Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18903>
This commit is contained in:
Konstantin Seurer
2024-04-06 10:05:41 +02:00
committed by Marge Bot
parent 4423c50c1b
commit 81e3930ec0
2 changed files with 109 additions and 9 deletions
+2
View File
@@ -5149,6 +5149,8 @@ char *nir_shader_as_str(nir_shader *nir, void *mem_ctx);
char *nir_shader_as_str_annotated(nir_shader *nir, struct hash_table *annotations, void *mem_ctx);
char *nir_instr_as_str(const nir_instr *instr, void *mem_ctx);
char *nir_shader_gather_debug_info(nir_shader *shader, const char *filename);
/** Shallow clone of a single instruction. */
nir_instr *nir_instr_clone(nir_shader *s, const nir_instr *orig);
+107 -9
View File
@@ -35,6 +35,7 @@
#include "util/mesa-blake3.h"
#include "vulkan/vulkan_core.h"
#include "nir.h"
#include "nir_builder.h"
static void
print_indentation(unsigned levels, FILE *fp)
@@ -46,6 +47,9 @@ print_indentation(unsigned levels, FILE *fp)
typedef struct {
FILE *fp;
nir_shader *shader;
const char *def_prefix;
/** map from nir_variable -> printable name */
struct hash_table *ht;
@@ -75,6 +79,8 @@ typedef struct {
* them align with the `=` for instructions with destination.
*/
unsigned padding_for_no_dest;
nir_debug_info_instr **debug_info;
} print_state;
static void
@@ -125,10 +131,10 @@ print_def(nir_def *def, print_state *state)
const unsigned padding = (def->bit_size == 1) + 1 + ssa_padding;
fprintf(fp, "%s%u%s%*s%%%u",
fprintf(fp, "%s%u%s%*s%s%u",
divergence_status(state, def->divergent),
def->bit_size, sizes[def->num_components],
padding, "", def->index);
padding, "", state->def_prefix, def->index);
}
static unsigned
@@ -389,7 +395,7 @@ static void
print_src(const nir_src *src, print_state *state, nir_alu_type src_type)
{
FILE *fp = state->fp;
fprintf(fp, "%%%u", src->ssa->index);
fprintf(fp, "%s%u", state->def_prefix, src->ssa->index);
nir_instr *instr = src->ssa->parent_instr;
if (instr->type == nir_instr_type_load_const && !NIR_DEBUG(PRINT_NO_INLINE_CONSTS)) {
@@ -1994,6 +2000,12 @@ static void
print_instr(const nir_instr *instr, print_state *state, unsigned tabs)
{
FILE *fp = state->fp;
if (state->debug_info) {
nir_debug_info_instr *di = state->debug_info[instr->index];
di->src_loc.column = (uint32_t)ftell(fp);
}
print_indentation(tabs, fp);
switch (instr->type) {
@@ -2654,13 +2666,16 @@ print_shader_info(const struct shader_info *info, FILE *fp)
}
}
void
nir_print_shader_annotated(nir_shader *shader, FILE *fp,
struct hash_table *annotations)
static void
_nir_print_shader_annotated(nir_shader *shader, FILE *fp,
struct hash_table *annotations,
nir_debug_info_instr **debug_info)
{
print_state state;
init_print_state(&state, shader, fp);
state.def_prefix = debug_info ? "ssa_" : "%";
state.annotations = annotations;
state.debug_info = debug_info;
print_shader_info(&shader->info, fp);
@@ -2701,6 +2716,13 @@ nir_print_shader_annotated(nir_shader *shader, FILE *fp,
destroy_print_state(&state);
}
void
nir_print_shader_annotated(nir_shader *shader, FILE *fp,
struct hash_table *annotations)
{
_nir_print_shader_annotated(shader, fp, annotations, NULL);
}
void
nir_print_shader(nir_shader *shader, FILE *fp)
{
@@ -2708,15 +2730,16 @@ nir_print_shader(nir_shader *shader, FILE *fp)
fflush(fp);
}
char *
nir_shader_as_str_annotated(nir_shader *nir, struct hash_table *annotations, void *mem_ctx)
static char *
_nir_shader_as_str_annotated(nir_shader *nir, struct hash_table *annotations, void *mem_ctx,
nir_debug_info_instr **debug_info)
{
char *stream_data = NULL;
size_t stream_size = 0;
struct u_memstream mem;
if (u_memstream_open(&mem, &stream_data, &stream_size)) {
FILE *const stream = u_memstream_get(&mem);
nir_print_shader_annotated(nir, stream, annotations);
_nir_print_shader_annotated(nir, stream, annotations, debug_info);
u_memstream_close(&mem);
}
@@ -2729,6 +2752,12 @@ nir_shader_as_str_annotated(nir_shader *nir, struct hash_table *annotations, voi
return str;
}
char *
nir_shader_as_str_annotated(nir_shader *nir, struct hash_table *annotations, void *mem_ctx)
{
return _nir_shader_as_str_annotated(nir, annotations, mem_ctx, NULL);
}
char *
nir_shader_as_str(nir_shader *nir, void *mem_ctx)
{
@@ -2740,6 +2769,7 @@ nir_print_instr(const nir_instr *instr, FILE *fp)
{
print_state state = {
.fp = fp,
.def_prefix = "%",
};
if (instr->block) {
nir_function_impl *impl = nir_cf_node_get_function(&instr->block->cf_node);
@@ -2775,6 +2805,7 @@ nir_print_deref(const nir_deref_instr *deref, FILE *fp)
{
print_state state = {
.fp = fp,
.def_prefix = "%",
};
print_deref_link(deref, true, &state);
}
@@ -2787,3 +2818,70 @@ nir_log_shader_annotated_tagged(enum mesa_log_level level, const char *tag,
_mesa_log_multiline(level, tag, str);
ralloc_free(str);
}
char *
nir_shader_gather_debug_info(nir_shader *shader, const char *filename)
{
uint32_t instr_count = 0;
nir_foreach_function_impl(impl, shader) {
nir_foreach_block(block, impl) {
nir_foreach_instr(instr, block) {
instr->index = instr_count;
instr_count++;
}
}
}
if (!instr_count)
return nir_shader_as_str(shader, NULL);
nir_debug_info_instr **debug_info = rzalloc_array(shader, nir_debug_info_instr *, instr_count);
instr_count = 0;
nir_foreach_function_impl(impl, shader) {
nir_builder b = nir_builder_at(nir_before_cf_list(&impl->body));
nir_def *filename_def = nir_build_string(&b, filename);
nir_foreach_block(block, impl) {
nir_foreach_instr_safe(instr, block) {
if (instr->type == nir_instr_type_debug_info)
continue;
nir_debug_info_instr *di = nir_debug_info_instr_create(shader, nir_debug_info_src_loc, 0);
di->src_loc.filename = nir_src_for_ssa(filename_def);
di->src_loc.source = nir_debug_info_nir;
debug_info[instr_count++] = di;
}
}
}
char *str = _nir_shader_as_str_annotated(shader, NULL, NULL, debug_info);
uint32_t line = 1;
uint32_t character_index = 0;
for (uint32_t i = 0; i < instr_count; i++) {
nir_debug_info_instr *di = debug_info[i];
while (character_index < di->src_loc.column) {
if (str[character_index] == '\n')
line++;
character_index++;
}
di->src_loc.line = line;
di->src_loc.column = 0;
}
instr_count = 0;
nir_foreach_function_impl(impl, shader) {
nir_foreach_block(block, impl) {
nir_foreach_instr_safe(instr, block) {
if (instr->type != nir_instr_type_debug_info)
nir_instr_insert_before(instr, &debug_info[instr_count++]->instr);
}
}
}
return str;
}