[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