summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolai Hähnle <nicolai.haehnle@amd.com>2018-01-18 16:05:21 +0100
committerNicolai Hähnle <nicolai.haehnle@amd.com>2018-04-11 12:44:30 +0200
commit41e6ffee49832c57b3821e4b63e0245db7b115f9 (patch)
tree9909f223dde494991cf1b3a6d07601264afc61d7
parent0630e52c9eba4af9b1e96705248bad03a0cb951e (diff)
radeonsi: correctly parse disassembly with labels
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. Reviewed-by: Marek Olšák <marek.olsak@amd.com>
-rw-r--r--src/gallium/drivers/radeonsi/si_debug.c63
1 files changed, 32 insertions, 31 deletions
diff --git a/src/gallium/drivers/radeonsi/si_debug.c b/src/gallium/drivers/radeonsi/si_debug.c
index 69d20c1efe..817a6d5ee9 100644
--- a/src/gallium/drivers/radeonsi/si_debug.c
+++ b/src/gallium/drivers/radeonsi/si_debug.c
@@ -31,6 +31,7 @@
#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,
@@ -859,42 +860,40 @@ static void si_dump_compute_descriptors(struct si_context *sctx,
}
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;
}
}
@@ -930,26 +929,27 @@ static void si_print_annotated_shader(struct si_shader *shader,
* 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",
@@ -959,10 +959,11 @@ static void si_print_annotated_shader(struct si_shader *shader,
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 " ",