[Mesa-dev] [PATCH 2/2] radeonsi: correctly parse disassembly with labels

Marek Olšák maraeo at gmail.com
Mon Jan 29 22:04:36 UTC 2018


For the series:

Reviewed-by: Marek Olšák <marek.olsak at amd.com>

Marek

On Tue, Jan 23, 2018 at 11:17 AM, Nicolai Hähnle <nhaehnle at gmail.com> wrote:
> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
>
> LLVM now emits labels as part of the disassembly string, which is very
> useful but breaks the old parsing approach.
>
> Use the semicolon to detect the boundary of instructions instead of going
> by line breaks.
> ---
>  src/gallium/drivers/radeonsi/si_debug.c | 63 +++++++++++++++++----------------
>  1 file changed, 32 insertions(+), 31 deletions(-)
>
> diff --git a/src/gallium/drivers/radeonsi/si_debug.c b/src/gallium/drivers/radeonsi/si_debug.c
> index b24d5e705f5..8334c49a0ee 100644
> --- a/src/gallium/drivers/radeonsi/si_debug.c
> +++ b/src/gallium/drivers/radeonsi/si_debug.c
> @@ -23,20 +23,21 @@
>
>  #include "si_pipe.h"
>  #include "si_compute.h"
>  #include "sid.h"
>  #include "gfx9d.h"
>  #include "sid_tables.h"
>  #include "ddebug/dd_util.h"
>  #include "util/u_dump.h"
>  #include "util/u_log.h"
>  #include "util/u_memory.h"
> +#include "util/u_string.h"
>  #include "ac_debug.h"
>
>  static void si_dump_bo_list(struct si_context *sctx,
>                             const struct radeon_saved_cs *saved, FILE *f);
>
>  DEBUG_GET_ONCE_OPTION(replace_shaders, "RADEON_REPLACE_SHADERS", NULL)
>
>  static void si_dump_shader(struct si_screen *sscreen,
>                            enum pipe_shader_type processor,
>                            const struct si_shader *shader, FILE *f)
> @@ -783,56 +784,54 @@ static void si_dump_gfx_descriptors(struct si_context *sctx,
>  static void si_dump_compute_descriptors(struct si_context *sctx,
>                                         struct u_log_context *log)
>  {
>         if (!sctx->cs_shader_state.program)
>                 return;
>
>         si_dump_descriptors(sctx, PIPE_SHADER_COMPUTE, NULL, log);
>  }
>
>  struct si_shader_inst {
> -       char text[160];  /* one disasm line */
> -       unsigned offset; /* instruction offset */
> +       const char *text; /* start of disassembly for this instruction */
> +       unsigned textlen;
>         unsigned size;   /* instruction size = 4 or 8 */
> +       uint64_t addr; /* instruction address */
>  };
>
> -/* Split a disassembly string into lines and add them to the array pointed
> - * to by "instructions". */
> +/**
> + * Split a disassembly string into instructions and add them to the array
> + * pointed to by \p instructions.
> + *
> + * Labels are considered to be part of the following instruction.
> + */
>  static void si_add_split_disasm(const char *disasm,
> -                               uint64_t start_addr,
> +                               uint64_t *addr,
>                                 unsigned *num,
>                                 struct si_shader_inst *instructions)
>  {
> -       struct si_shader_inst *last_inst = *num ? &instructions[*num - 1] : NULL;
> -       char *next;
> +       const char *semicolon;
>
> -       while ((next = strchr(disasm, '\n'))) {
> -               struct si_shader_inst *inst = &instructions[*num];
> -               unsigned len = next - disasm;
> +       while ((semicolon = strchr(disasm, ';'))) {
> +               struct si_shader_inst *inst = &instructions[(*num)++];
> +               const char *end = util_strchrnul(semicolon, '\n');
>
> -               assert(len < ARRAY_SIZE(inst->text));
> -               memcpy(inst->text, disasm, len);
> -               inst->text[len] = 0;
> -               inst->offset = last_inst ? last_inst->offset + last_inst->size : 0;
> +               inst->text = disasm;
> +               inst->textlen = end - disasm;
>
> -               const char *semicolon = strchr(disasm, ';');
> -               assert(semicolon);
> +               inst->addr = *addr;
>                 /* More than 16 chars after ";" means the instruction is 8 bytes long. */
> -               inst->size = next - semicolon > 16 ? 8 : 4;
> -
> -               snprintf(inst->text + len, ARRAY_SIZE(inst->text) - len,
> -                       " [PC=0x%"PRIx64", off=%u, size=%u]",
> -                       start_addr + inst->offset, inst->offset, inst->size);
> +               inst->size = end - semicolon > 16 ? 8 : 4;
> +               *addr += inst->size;
>
> -               last_inst = inst;
> -               (*num)++;
> -               disasm = next + 1;
> +               if (!(*end))
> +                       break;
> +               disasm = end + 1;
>         }
>  }
>
>  /* If the shader is being executed, print its asm instructions, and annotate
>   * those that are being executed right now with information about waves that
>   * execute them. This is most useful during a GPU hang.
>   */
>  static void si_print_annotated_shader(struct si_shader *shader,
>                                       struct ac_wave_info *waves,
>                                       unsigned num_waves,
> @@ -854,53 +853,55 @@ static void si_print_annotated_shader(struct si_shader *shader,
>                 return; /* the shader is not being executed */
>
>         /* Remember the first found wave. The waves are sorted according to PC. */
>         waves = &waves[i];
>         num_waves -= i;
>
>         /* Get the list of instructions.
>          * Buffer size / 4 is the upper bound of the instruction count.
>          */
>         unsigned num_inst = 0;
> +       uint64_t inst_addr = start_addr;
>         struct si_shader_inst *instructions =
>                 calloc(shader->bo->b.b.width0 / 4, sizeof(struct si_shader_inst));
>
>         if (shader->prolog) {
>                 si_add_split_disasm(shader->prolog->binary.disasm_string,
> -                                   start_addr, &num_inst, instructions);
> +                                   &inst_addr, &num_inst, instructions);
>         }
>         if (shader->previous_stage) {
>                 si_add_split_disasm(shader->previous_stage->binary.disasm_string,
> -                                   start_addr, &num_inst, instructions);
> +                                   &inst_addr, &num_inst, instructions);
>         }
>         if (shader->prolog2) {
>                 si_add_split_disasm(shader->prolog2->binary.disasm_string,
> -                                   start_addr, &num_inst, instructions);
> +                                   &inst_addr, &num_inst, instructions);
>         }
>         si_add_split_disasm(shader->binary.disasm_string,
> -                           start_addr, &num_inst, instructions);
> +                           &inst_addr, &num_inst, instructions);
>         if (shader->epilog) {
>                 si_add_split_disasm(shader->epilog->binary.disasm_string,
> -                                   start_addr, &num_inst, instructions);
> +                                   &inst_addr, &num_inst, instructions);
>         }
>
>         fprintf(f, COLOR_YELLOW "%s - annotated disassembly:" COLOR_RESET "\n",
>                 si_get_shader_name(shader, shader->selector->type));
>
>         /* Print instructions with annotations. */
>         for (i = 0; i < num_inst; i++) {
>                 struct si_shader_inst *inst = &instructions[i];
>
> -               fprintf(f, "%s\n", inst->text);
> +               fprintf(f, "%.*s [PC=0x%"PRIx64", size=%u]\n",
> +                       inst->textlen, inst->text, inst->addr, inst->size);
>
>                 /* Print which waves execute the instruction right now. */
> -               while (num_waves && start_addr + inst->offset == waves->pc) {
> +               while (num_waves && inst->addr == waves->pc) {
>                         fprintf(f,
>                                 "          " COLOR_GREEN "^ SE%u SH%u CU%u "
>                                 "SIMD%u WAVE%u  EXEC=%016"PRIx64 "  ",
>                                 waves->se, waves->sh, waves->cu, waves->simd,
>                                 waves->wave, waves->exec);
>
>                         if (inst->size == 4) {
>                                 fprintf(f, "INST32=%08X" COLOR_RESET "\n",
>                                         waves->inst_dw0);
>                         } else {
> --
> 2.11.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list