On 01.07.2016 01:21, Marek Olšák wrote:
From: Marek Olšák <marek.ol...@amd.com>

Getting LLVM IRs of hanging shaders have never been easier.
---
  src/gallium/drivers/radeon/r600_pipe_common.c   |  1 +
  src/gallium/drivers/radeon/r600_pipe_common.h   |  1 +
  src/gallium/drivers/radeonsi/si_pipe.c          |  3 +++
  src/gallium/drivers/radeonsi/si_pipe.h          |  1 +
  src/gallium/drivers/radeonsi/si_shader.c        | 12 ++++++++++++
  src/gallium/drivers/radeonsi/si_state_shaders.c |  9 ++++++++-
  6 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c 
b/src/gallium/drivers/radeon/r600_pipe_common.c
index 5e981d6..74674e7 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.c
+++ b/src/gallium/drivers/radeon/r600_pipe_common.c
@@ -67,6 +67,7 @@ void radeon_shader_binary_clean(struct radeon_shader_binary 
*b)
        FREE(b->global_symbol_offsets);
        FREE(b->relocs);
        FREE(b->disasm_string);
+       FREE(b->llvm_ir_string);
  }

  /*
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h 
b/src/gallium/drivers/radeon/r600_pipe_common.h
index c145dc3..1ad69f8 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -155,6 +155,7 @@ struct radeon_shader_binary {

        /** Disassembled shader in a string. */
        char *disasm_string;
+       char *llvm_ir_string;
  };

  void radeon_shader_binary_init(struct radeon_shader_binary *b);
diff --git a/src/gallium/drivers/radeonsi/si_pipe.c 
b/src/gallium/drivers/radeonsi/si_pipe.c
index f15e589..ad2a86a 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.c
+++ b/src/gallium/drivers/radeonsi/si_pipe.c
@@ -139,6 +139,9 @@ static struct pipe_context *si_create_context(struct 
pipe_screen *screen,
        if (sscreen->b.debug_flags & DBG_CHECK_VM)
                flags |= PIPE_CONTEXT_DEBUG;

+       if (flags & PIPE_CONTEXT_DEBUG)
+               sscreen->record_llvm_ir = true; /* racy but not critical */
+
        sctx->b.b.screen = screen; /* this must be set first */
        sctx->b.b.priv = priv;
        sctx->b.b.destroy = si_destroy_context;
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h 
b/src/gallium/drivers/radeonsi/si_pipe.h
index 9d15cbf..fc7e73e 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -87,6 +87,7 @@ struct si_screen {

        /* Whether shaders are monolithic (1-part) or separate (3-part). */
        bool                            use_monolithic_shaders;
+       bool                            record_llvm_ir;

        pipe_mutex                      shader_parts_mutex;
        struct si_shader_part           *vs_prologs;
diff --git a/src/gallium/drivers/radeonsi/si_shader.c 
b/src/gallium/drivers/radeonsi/si_shader.c
index bba6a55..e2aae85 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -6159,6 +6159,12 @@ void si_shader_dump(struct si_screen *sscreen, struct 
si_shader *shader,
                    struct pipe_debug_callback *debug, unsigned processor,
                    FILE *file)
  {
+       if (file != stderr && shader->binary.llvm_ir_string) {
+               fprintf(file, "\n%s - main shader part - LLVM IR:\n\n",
+                       si_get_shader_name(shader, processor));
+               fprintf(file, "%s\n", shader->binary.llvm_ir_string);
+       }
+
        if (file != stderr ||
            (r600_can_dump_shader(&sscreen->b, processor) &&
             !(sscreen->b.debug_flags & DBG_NO_ASM))) {
@@ -6204,6 +6210,12 @@ int si_compile_llvm(struct si_screen *sscreen,
                }
        }

+       if (sscreen->record_llvm_ir) {
+               char *ir = LLVMPrintModuleToString(mod);
+               binary->llvm_ir_string = strdup(ir);
+               LLVMDisposeMessage(ir);
+       }
+
        if (!si_replace_shader(count, binary)) {
                r = radeon_llvm_compile(mod, binary, tm, debug);
                if (r)
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c 
b/src/gallium/drivers/radeonsi/si_state_shaders.c
index 4bcdeb6..ed14288 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -96,6 +96,8 @@ static uint32_t *read_chunk(uint32_t *ptr, void **data, 
unsigned *size)
  {
        *size = *ptr++;
        assert(*data == NULL);
+       if (!*size)
+               return ptr;
        *data = malloc(*size);
        return read_data(ptr, *data, *size);
  }
@@ -110,6 +112,8 @@ static void *si_get_shader_binary(struct si_shader *shader)
        unsigned relocs_size = shader->binary.reloc_count *
                               sizeof(shader->binary.relocs[0]);
        unsigned disasm_size = strlen(shader->binary.disasm_string) + 1;
+       unsigned llvm_ir_size = shader->binary.llvm_ir_string ?
+                               strlen(shader->binary.llvm_ir_string) + 1 : 0;

I don't believe it's crashing right now, but this is a bit fragile: in the case where llvm_ir_string is originally NULL, when the chunk is read back one allocates a 0-sized buffer, which may be a non-NULL pointer at garbage.

I'd be fine with fixing that by changing read_chunk accordingly.

Nicolai

        unsigned size =
                4 + /* total size */
                4 + /* CRC32 of the data below */
@@ -118,7 +122,8 @@ static void *si_get_shader_binary(struct si_shader *shader)
                4 + align(shader->binary.code_size, 4) +
                4 + align(shader->binary.rodata_size, 4) +
                4 + align(relocs_size, 4) +
-               4 + align(disasm_size, 4);
+               4 + align(disasm_size, 4) +
+               4 + align(llvm_ir_size, 4);
        void *buffer = CALLOC(1, size);
        uint32_t *ptr = (uint32_t*)buffer;

@@ -134,6 +139,7 @@ static void *si_get_shader_binary(struct si_shader *shader)
        ptr = write_chunk(ptr, shader->binary.rodata, 
shader->binary.rodata_size);
        ptr = write_chunk(ptr, shader->binary.relocs, relocs_size);
        ptr = write_chunk(ptr, shader->binary.disasm_string, disasm_size);
+       ptr = write_chunk(ptr, shader->binary.llvm_ir_string, llvm_ir_size);
        assert((char *)ptr - (char *)buffer == size);

        /* Compute CRC32. */
@@ -165,6 +171,7 @@ static bool si_load_shader_binary(struct si_shader *shader, 
void *binary)
        ptr = read_chunk(ptr, (void**)&shader->binary.relocs, &chunk_size);
        shader->binary.reloc_count = chunk_size / 
sizeof(shader->binary.relocs[0]);
        ptr = read_chunk(ptr, (void**)&shader->binary.disasm_string, 
&chunk_size);
+       ptr = read_chunk(ptr, (void**)&shader->binary.llvm_ir_string, 
&chunk_size);

        return true;
  }

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to