[Mesa-dev] [PATCH 2/2] radeonsi: correctly parse disassembly with labels
Nicolai Hähnle
nhaehnle at gmail.com
Tue Jan 23 10:17:56 UTC 2018
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
More information about the mesa-dev
mailing list