[Mesa-dev] [PATCH 18/18] intel/tools: add command line GEN shader disassembler tool

Eric Engestrom eric.engestrom at imgtec.com
Mon Nov 13 18:09:17 UTC 2017


On Monday, 2017-11-13 15:18:06 +0200, kevin.rogovin at intel.com wrote:
> From: Kevin Rogovin <kevin.rogovin at intel.com>
> 
> Signed-off-by: Kevin Rogovin <kevin.rogovin at intel.com>
> ---
>  src/intel/Makefile.tools.am               |  21 ++-
>  src/intel/tools/.gitignore                |   1 +
>  src/intel/tools/gen_shader_disassembler.c | 221 ++++++++++++++++++++++++++++++
>  3 files changed, 242 insertions(+), 1 deletion(-)
>  create mode 100644 src/intel/tools/gen_shader_disassembler.c
> 
> diff --git a/src/intel/Makefile.tools.am b/src/intel/Makefile.tools.am
> index dd68d8f173..71eb3253c3 100644
> --- a/src/intel/Makefile.tools.am
> +++ b/src/intel/Makefile.tools.am
> @@ -32,7 +32,8 @@ intellib_LTLIBRARIES = \
>  
>  intelbin_PROGRAMS = tools/i965_batchbuffer_dump_show \
>  	tools/i965_batchbuffer_dump_show_xml \
> -	tools/i965_batchbuffer_dump_show_json
> +	tools/i965_batchbuffer_dump_show_json \
> +	tools/gen_shader_disassembler

Could you add these to src/intel/tools/meson.build as well?
Thanks :)

>  
>  intelbin_SCRIPTS = tools/i965_batchbuffer_logger_sh
>  CLEANFILES += $(intelbin_SCRIPTS)
> @@ -111,3 +112,21 @@ tools_i965_batchbuffer_dump_show_xml_SOURCES = \
>  
>  tools_i965_batchbuffer_dump_show_json_SOURCES = \
>  	tools/i965_batchbuffer_dump_show_json.cpp
> +
> +tools_gen_shader_disassembler_SOURCES = \
> +	tools/gen_shader_disassembler.c \
> +	tools/disasm.c \
> +	tools/gen_disasm.h
> +
> +tools_gen_shader_disassembler_LDADD = \
> +	common/libintel_common.la \
> +	compiler/libintel_compiler.la \
> +	$(top_builddir)/src/util/libmesautil.la \
> +	$(PTHREAD_LIBS) \
> +	$(EXPAT_LIBS) \
> +	$(ZLIB_LIBS)
> +
> +tools_gen_shader_disassembler_CFLAGS = \
> +	$(AM_CFLAGS) \
> +	$(EXPAT_CFLAGS) \
> +	$(ZLIB_CFLAGS)
> diff --git a/src/intel/tools/.gitignore b/src/intel/tools/.gitignore
> index ea4dc23c20..e9b22c89aa 100644
> --- a/src/intel/tools/.gitignore
> +++ b/src/intel/tools/.gitignore
> @@ -4,3 +4,4 @@
>  /i965_batchbuffer_dump_show
>  /i965_batchbuffer_dump_show_xml
>  /i965_batchbuffer_dump_show_json
> +/gen_shader_disassembler
> diff --git a/src/intel/tools/gen_shader_disassembler.c b/src/intel/tools/gen_shader_disassembler.c
> new file mode 100644
> index 0000000000..bd6c400fcc
> --- /dev/null
> +++ b/src/intel/tools/gen_shader_disassembler.c
> @@ -0,0 +1,221 @@
> +/*
> + * Copyright © 2017 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + */
> +
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <stdlib.h>
> +#include <stdbool.h>
> +#include <getopt.h>
> +#include <strings.h>
> +
> +#include "compiler/brw_inst.h"
> +#include "compiler/brw_eu.h"
> +
> +static
> +void
> +print_opcodes(const void *data, int data_sz,
> +              struct gen_device_info *devinfo,
> +              bool print_offsets)
> +{
> +   for (int offset = 0; offset < data_sz;) {
> +      const brw_inst *insn = data + offset;
> +      bool compacted;
> +      brw_inst uncompacted;
> +      enum opcode opcode;
> +      const struct opcode_desc *desc;
> +
> +      if (print_offsets) {
> +         printf("0x%08x: ", offset);
> +      }
> +
> +      compacted = brw_inst_cmpt_control(devinfo, insn);
> +      if (compacted) {
> +         brw_compact_inst *compacted_insn;
> +         compacted_insn = (void*)insn;
> +         brw_uncompact_instruction(devinfo, &uncompacted, compacted_insn);
> +         insn = &uncompacted;
> +         offset += 8;
> +      } else {
> +         offset += 16;
> +      }
> +
> +      opcode = brw_inst_opcode(devinfo, insn);
> +      desc = brw_opcode_desc(devinfo, opcode);
> +      if (desc) {
> +         printf("(0x%08x) %s", opcode, desc->name);
> +      } else {
> +         printf("(0x%08x) UnknownOpcode", opcode);
> +      }
> +
> +      if (compacted) {
> +         printf(" {Compacted}");
> +      }
> +
> +      printf("\n");
> +   }
> +}
> +
> +static
> +void
> +print_disassembly(const void *data, int data_sz,
> +                  struct gen_device_info *devinfo,
> +                  bool print_offsets)
> +{
> +   struct annotation_info annotation_info = {
> +      .ann_count = 1,
> +      .ann_size = 2,
> +   };
> +   annotation_info.mem_ctx = ralloc_context(NULL);
> +   annotation_info.ann = rzalloc_array(annotation_info.mem_ctx,
> +                                       struct annotation,
> +                                       annotation_info.ann_size);
> +   annotation_info.ann[0].offset = 0;
> +   annotation_info.ann[1].offset = data_sz;
> +   brw_validate_instructions(devinfo, data, 0, data_sz, &annotation_info);
> +   struct annotation *annotation = annotation_info.ann;
> +   int offset = 0;
> +
> +   for (int i = 0; i < annotation_info.ann_count; i++) {
> +      int end_offset = annotation[i + 1].offset;
> +
> +      brw_disassemble_print_offset_option(devinfo, data, offset,
> +                                          end_offset, stdout, print_offsets);
> +
> +      if (annotation[i].error) {
> +         fputs(annotation[i].error, stdout);
> +      }
> +
> +      offset = end_offset;
> +   }
> +
> +   if (offset < data_sz) {
> +      brw_disassemble_print_offset_option(devinfo, data, offset,
> +                                          data_sz, stdout, print_offsets);
> +   }
> +
> +   ralloc_free(annotation_info.mem_ctx);
> +}
> +
> +static
> +void
> +print_help(FILE *p, const char *argv0)
> +{
> +   fprintf(p, "Usage: %s [OPTION] ShaderBinary\n"
> +           "  -p   PCI ID of GPU for which shader binary was generated, must be given;\n"
> +           "       if the value is of the form 0xVALUE, then read the value as hex;\n"
> +           "       if the value is of the form 0VALUE, then read the value as oct;\n"
> +           "       otherwise read the value as decimal\n"
> +           "  -c   Print opcodes only instead of disassembly\n"
> +           "  -o   Print offsets into ShaderBinary\n"
> +           "  -h   Print this help message and quit\n", argv0);
> +}
> +
> +int
> +main(int argc, char **argv)
> +{
> +   const char *short_options = "p:oc";
> +   FILE *file;
> +   void *data;
> +   int data_sz, pci_id, data_read;
> +   bool pci_id_provided = false, print_opcodes_only = false;
> +   bool print_offsets = false;
> +   struct gen_device_info devinfo;
> +
> +   int opt;
> +   while ((opt = getopt(argc, argv, short_options)) != -1) {
> +      switch(opt) {
> +      case 'p':
> +         pci_id_provided = true;
> +         pci_id = strtol(optarg, NULL, 0);
> +         break;
> +      case 'c':
> +         print_opcodes_only = true;
> +         break;
> +      case 'o':
> +         print_offsets = true;
> +         break;
> +      case 'h':
> +         print_help(stdout, argv[0]);
> +         return 0;
> +      default:
> +         fprintf(stderr, "Unknown option '%c'\n", (char)opt);
> +         print_help(stderr, argv[0]);
> +      }
> +   }
> +
> +   if (optind >= argc) {
> +      fprintf(stderr, "Need to proviade ShaderBinary file.\n");
> +      print_help(stderr, argv[0]);
> +      return -1;
> +   }
> +
> +   if (!pci_id_provided) {
> +      fprintf(stderr, "Need to provide PCI ID with -p option\n");
> +      return -1;
> +   }
> +
> +   if(!gen_get_device_info(pci_id, &devinfo)) {
> +      fprintf(stderr, "Bad PCIID 0x%x given, aborting\n", pci_id);
> +      return -1;
> +   }
> +
> +   file = fopen(argv[optind], "r");
> +   if (file == NULL) {
> +      fprintf(stderr, "Unable to open file \"%s\" for reading, aborting\n",
> +              argv[optind]);
> +      return -1;
> +   }
> +
> +   fseek(file, 0, SEEK_END);
> +   data_sz = ftell(file);
> +   fseek(file, 0, SEEK_SET);
> +
> +   data = malloc(data_sz);
> +   if (data == NULL) {
> +      fprintf(stderr,
> +              "Failed to allocate %d bytes to hold file contents.\n",
> +              data_sz);
> +      return -1;
> +   }
> +
> +   data_read = fread(data, 1, data_sz, file);
> +   if (data_read != data_sz) {
> +      fprintf(stderr,
> +              "Failed to read entire file \"%s\", read %d of %d bytes\n",
> +              argv[optind], data_read, data_sz);
> +      free(data);
> +      fclose(file);
> +      return -1;
> +   }
> +
> +   brw_init_compaction_tables(&devinfo);
> +   if (print_opcodes_only) {
> +      print_opcodes(data, data_sz, &devinfo, print_offsets);
> +   } else {
> +      print_disassembly(data, data_sz, &devinfo, print_offsets);
> +   }
> +
> +   free(data);
> +   fclose(file);
> +   return 0;
> +}
> -- 
> 2.14.2
> 


More information about the mesa-dev mailing list