17ec681f3Smrg/*
27ec681f3Smrg * Copyright © Microsoft Corporation
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
217ec681f3Smrg * IN THE SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include "dxil_dump.h"
257ec681f3Smrg#include "dxil_internal.h"
267ec681f3Smrg
277ec681f3Smrg#define DIXL_DUMP_DECL
287ec681f3Smrg#include "dxil_dump_decls.h"
297ec681f3Smrg
307ec681f3Smrg#include "dxil_module.h"
317ec681f3Smrg
327ec681f3Smrg
337ec681f3Smrg#include "util/string_buffer.h"
347ec681f3Smrg#include "util/list.h"
357ec681f3Smrg
367ec681f3Smrg#include <stdio.h>
377ec681f3Smrg
387ec681f3Smrgstruct dxil_dumper {
397ec681f3Smrg   struct _mesa_string_buffer *buf;
407ec681f3Smrg   int current_indent;
417ec681f3Smrg};
427ec681f3Smrg
437ec681f3Smrgstruct dxil_dumper *dxil_dump_create(void)
447ec681f3Smrg{
457ec681f3Smrg   struct dxil_dumper *d = calloc(1, sizeof(struct dxil_dumper));
467ec681f3Smrg   d->buf = _mesa_string_buffer_create(NULL, 1024);
477ec681f3Smrg   d->current_indent = 0;
487ec681f3Smrg   return d;
497ec681f3Smrg}
507ec681f3Smrg
517ec681f3Smrgvoid dxil_dump_free(struct dxil_dumper *d)
527ec681f3Smrg{
537ec681f3Smrg   _mesa_string_buffer_destroy(d->buf);
547ec681f3Smrg   d->buf = 0;
557ec681f3Smrg   free(d);
567ec681f3Smrg}
577ec681f3Smrg
587ec681f3Smrgvoid dxil_dump_buf_to_file(struct dxil_dumper *d, FILE *f)
597ec681f3Smrg{
607ec681f3Smrg   assert(f);
617ec681f3Smrg   assert(d);
627ec681f3Smrg   assert(d->buf);
637ec681f3Smrg   fprintf(f, "%s", d->buf->buf);
647ec681f3Smrg}
657ec681f3Smrg
667ec681f3Smrgstatic
677ec681f3Smrgvoid dxil_dump_indention_inc(struct dxil_dumper *d)
687ec681f3Smrg{
697ec681f3Smrg   ++d->current_indent;
707ec681f3Smrg}
717ec681f3Smrg
727ec681f3Smrgstatic
737ec681f3Smrgvoid dxil_dump_indention_dec(struct dxil_dumper *d)
747ec681f3Smrg{
757ec681f3Smrg   --d->current_indent;
767ec681f3Smrg   assert(d->current_indent >= 0);
777ec681f3Smrg}
787ec681f3Smrg
797ec681f3Smrgstatic
807ec681f3Smrgvoid dxil_dump_indent(struct dxil_dumper *d)
817ec681f3Smrg{
827ec681f3Smrg   for (int i = 0; i  < 2 * d->current_indent; ++i)
837ec681f3Smrg      _mesa_string_buffer_append_char(d->buf, ' ');
847ec681f3Smrg}
857ec681f3Smrg
867ec681f3Smrgvoid
877ec681f3Smrgdxil_dump_module(struct dxil_dumper *d, struct dxil_module *m)
887ec681f3Smrg{
897ec681f3Smrg   assert(m);
907ec681f3Smrg   assert(d);
917ec681f3Smrg
927ec681f3Smrg   _mesa_string_buffer_printf(d->buf, "DXIL MODULE:\n");
937ec681f3Smrg   dump_metadata(d, m);
947ec681f3Smrg   dump_shader_info(d, &m->info);
957ec681f3Smrg   dump_types(d, &m->type_list);
967ec681f3Smrg   dump_gvars(d, &m->gvar_list);
977ec681f3Smrg   dump_funcs(d, &m->func_list);
987ec681f3Smrg   dump_attr_set_list(d, &m->attr_set_list);
997ec681f3Smrg   dump_constants(d, &m->const_list);
1007ec681f3Smrg   dump_instrs(d, &m->instr_list);
1017ec681f3Smrg   dump_mdnodes(d, &m->mdnode_list);
1027ec681f3Smrg   dump_named_nodes(d, &m->md_named_node_list);
1037ec681f3Smrg   dump_io_signatures(d->buf, m);
1047ec681f3Smrg   dump_psv(d->buf, m);
1057ec681f3Smrg   _mesa_string_buffer_printf(d->buf, "END DXIL MODULE\n");
1067ec681f3Smrg}
1077ec681f3Smrg
1087ec681f3Smrgstatic void
1097ec681f3Smrgdump_metadata(struct dxil_dumper *d, struct dxil_module *m)
1107ec681f3Smrg{
1117ec681f3Smrg   _mesa_string_buffer_printf(d->buf, "Shader: %s\n",
1127ec681f3Smrg                              dump_shader_string(m->shader_kind));
1137ec681f3Smrg
1147ec681f3Smrg   _mesa_string_buffer_printf(d->buf, "Version: %d.%d\n",
1157ec681f3Smrg                              m->major_version, m->minor_version);
1167ec681f3Smrg
1177ec681f3Smrg   dump_features(d->buf, &m->feats);
1187ec681f3Smrg}
1197ec681f3Smrg
1207ec681f3Smrgstatic void
1217ec681f3Smrgdump_shader_info(struct dxil_dumper *d, struct dxil_shader_info *info)
1227ec681f3Smrg{
1237ec681f3Smrg   _mesa_string_buffer_append(d->buf, "Shader Info:\n");
1247ec681f3Smrg   if (info->has_out_position)
1257ec681f3Smrg      _mesa_string_buffer_append(d->buf, "  has_out_position\n");
1267ec681f3Smrg}
1277ec681f3Smrg
1287ec681f3Smrgstatic const char *
1297ec681f3Smrgdump_shader_string(enum dxil_shader_kind kind)
1307ec681f3Smrg{
1317ec681f3Smrg#define SHADER_STR(X) case DXIL_ ## X ## _SHADER: return #X
1327ec681f3Smrg
1337ec681f3Smrg   switch (kind) {
1347ec681f3Smrg   SHADER_STR(VERTEX);
1357ec681f3Smrg   SHADER_STR(PIXEL);
1367ec681f3Smrg   SHADER_STR(GEOMETRY);
1377ec681f3Smrg   SHADER_STR(COMPUTE);
1387ec681f3Smrg   default:
1397ec681f3Smrg      return "UNSUPPORTED";
1407ec681f3Smrg   }
1417ec681f3Smrg#undef SHADER_STR
1427ec681f3Smrg}
1437ec681f3Smrg
1447ec681f3Smrgstatic void
1457ec681f3Smrgdump_features(struct _mesa_string_buffer *buf, struct dxil_features *feat)
1467ec681f3Smrg{
1477ec681f3Smrg   _mesa_string_buffer_printf(buf, "Features:\n");
1487ec681f3Smrg#define PRINT_FEAT(F) if (feat->F) _mesa_string_buffer_printf(buf, "  %s\n", #F)
1497ec681f3Smrg   PRINT_FEAT(doubles);
1507ec681f3Smrg   PRINT_FEAT(cs_4x_raw_sb);
1517ec681f3Smrg   PRINT_FEAT(uavs_at_every_stage);
1527ec681f3Smrg   PRINT_FEAT(use_64uavs);
1537ec681f3Smrg   PRINT_FEAT(min_precision);
1547ec681f3Smrg   PRINT_FEAT(dx11_1_double_extensions);
1557ec681f3Smrg   PRINT_FEAT(dx11_1_shader_extensions);
1567ec681f3Smrg   PRINT_FEAT(dx9_comparison_filtering);
1577ec681f3Smrg   PRINT_FEAT(tiled_resources);
1587ec681f3Smrg   PRINT_FEAT(stencil_ref);
1597ec681f3Smrg   PRINT_FEAT(inner_coverage);
1607ec681f3Smrg   PRINT_FEAT(typed_uav_load_additional_formats);
1617ec681f3Smrg   PRINT_FEAT(rovs);
1627ec681f3Smrg   PRINT_FEAT(array_layer_from_vs_or_ds);
1637ec681f3Smrg   PRINT_FEAT(wave_ops);
1647ec681f3Smrg   PRINT_FEAT(int64_ops);
1657ec681f3Smrg   PRINT_FEAT(view_id);
1667ec681f3Smrg   PRINT_FEAT(barycentrics);
1677ec681f3Smrg   PRINT_FEAT(native_low_precision);
1687ec681f3Smrg   PRINT_FEAT(shading_rate);
1697ec681f3Smrg   PRINT_FEAT(raytracing_tier_1_1);
1707ec681f3Smrg   PRINT_FEAT(sampler_feedback);
1717ec681f3Smrg#undef PRINT_FEAT
1727ec681f3Smrg}
1737ec681f3Smrg
1747ec681f3Smrgstatic void
1757ec681f3Smrgdump_types(struct dxil_dumper *d, struct list_head *list)
1767ec681f3Smrg{
1777ec681f3Smrg   if (!list_length(list))
1787ec681f3Smrg      return;
1797ec681f3Smrg
1807ec681f3Smrg   _mesa_string_buffer_append(d->buf, "Types:\n");
1817ec681f3Smrg   dxil_dump_indention_inc(d);
1827ec681f3Smrg   list_for_each_entry(struct dxil_type, type, list, head) {
1837ec681f3Smrg      dxil_dump_indent(d);
1847ec681f3Smrg      dump_type(d, type);
1857ec681f3Smrg      _mesa_string_buffer_append(d->buf, "\n");
1867ec681f3Smrg   }
1877ec681f3Smrg   dxil_dump_indention_dec(d);
1887ec681f3Smrg}
1897ec681f3Smrg
1907ec681f3Smrgstatic void dump_type_name(struct dxil_dumper *d, const struct dxil_type *type)
1917ec681f3Smrg{
1927ec681f3Smrg   if (!type) {
1937ec681f3Smrg      _mesa_string_buffer_append(d->buf, "(type error)");
1947ec681f3Smrg      return;
1957ec681f3Smrg   }
1967ec681f3Smrg
1977ec681f3Smrg   switch (type->type) {
1987ec681f3Smrg   case TYPE_VOID:
1997ec681f3Smrg      _mesa_string_buffer_append(d->buf, "void");
2007ec681f3Smrg      break;
2017ec681f3Smrg   case TYPE_INTEGER:
2027ec681f3Smrg      _mesa_string_buffer_printf(d->buf, "int%d", type->int_bits);
2037ec681f3Smrg      break;
2047ec681f3Smrg   case TYPE_FLOAT:
2057ec681f3Smrg      _mesa_string_buffer_printf(d->buf, "float%d", type->float_bits);
2067ec681f3Smrg      break;
2077ec681f3Smrg   case TYPE_POINTER:
2087ec681f3Smrg      dump_type_name(d, type->ptr_target_type);
2097ec681f3Smrg      _mesa_string_buffer_append(d->buf, "*");
2107ec681f3Smrg      break;
2117ec681f3Smrg   case TYPE_STRUCT:
2127ec681f3Smrg      _mesa_string_buffer_printf(d->buf, "struct %s", type->struct_def.name);
2137ec681f3Smrg      break;
2147ec681f3Smrg   case TYPE_ARRAY:
2157ec681f3Smrg      dump_type_name(d, type->array_or_vector_def.elem_type);
2167ec681f3Smrg      _mesa_string_buffer_printf(d->buf, "[%d]", type->array_or_vector_def.num_elems);
2177ec681f3Smrg      break;
2187ec681f3Smrg   case TYPE_FUNCTION:
2197ec681f3Smrg      _mesa_string_buffer_append(d->buf, "(");
2207ec681f3Smrg      dump_type_name(d, type->function_def.ret_type);
2217ec681f3Smrg      _mesa_string_buffer_append(d->buf, ")(");
2227ec681f3Smrg      for (size_t i = 0; i < type->function_def.args.num_types; ++i) {
2237ec681f3Smrg         if (i > 0)
2247ec681f3Smrg            _mesa_string_buffer_append(d->buf, ", ");
2257ec681f3Smrg         dump_type_name(d, type->function_def.args.types[i]);
2267ec681f3Smrg      }
2277ec681f3Smrg      _mesa_string_buffer_append(d->buf, ")");
2287ec681f3Smrg      break;
2297ec681f3Smrg   case TYPE_VECTOR:
2307ec681f3Smrg      _mesa_string_buffer_append(d->buf, "vector<");
2317ec681f3Smrg      dump_type_name(d, type->array_or_vector_def.elem_type);
2327ec681f3Smrg      _mesa_string_buffer_printf(d->buf, ", %d>", type->array_or_vector_def.num_elems);
2337ec681f3Smrg      break;
2347ec681f3Smrg   default:
2357ec681f3Smrg      _mesa_string_buffer_printf(d->buf, "unknown type %d", type->type);
2367ec681f3Smrg   }
2377ec681f3Smrg}
2387ec681f3Smrg
2397ec681f3Smrgstatic void
2407ec681f3Smrgdump_type(struct dxil_dumper *d, const struct dxil_type *type)
2417ec681f3Smrg{
2427ec681f3Smrg   switch (type->type) {
2437ec681f3Smrg   case TYPE_STRUCT:
2447ec681f3Smrg      _mesa_string_buffer_printf(d->buf, "struct %s {\n", type->struct_def.name);
2457ec681f3Smrg      dxil_dump_indention_inc(d);
2467ec681f3Smrg
2477ec681f3Smrg      for (size_t i = 0; i < type->struct_def.elem.num_types; ++i) {
2487ec681f3Smrg         dxil_dump_indent(d);
2497ec681f3Smrg         dump_type(d, type->struct_def.elem.types[i]);
2507ec681f3Smrg         _mesa_string_buffer_append(d->buf, "\n");
2517ec681f3Smrg      }
2527ec681f3Smrg      dxil_dump_indention_dec(d);
2537ec681f3Smrg      dxil_dump_indent(d);
2547ec681f3Smrg      _mesa_string_buffer_append(d->buf, "}\n");
2557ec681f3Smrg      break;
2567ec681f3Smrg   default:
2577ec681f3Smrg      dump_type_name(d, type);
2587ec681f3Smrg      break;
2597ec681f3Smrg   }
2607ec681f3Smrg}
2617ec681f3Smrg
2627ec681f3Smrgstatic void
2637ec681f3Smrgdump_gvars(struct dxil_dumper *d, struct list_head *list)
2647ec681f3Smrg{
2657ec681f3Smrg   if (!list_length(list))
2667ec681f3Smrg      return;
2677ec681f3Smrg
2687ec681f3Smrg   _mesa_string_buffer_append(d->buf, "Global variables:\n");
2697ec681f3Smrg   dxil_dump_indention_inc(d);
2707ec681f3Smrg   list_for_each_entry(struct dxil_gvar, gvar, list, head) {
2717ec681f3Smrg      dxil_dump_indent(d);
2727ec681f3Smrg      _mesa_string_buffer_printf(d->buf, "address_space(%d) ", gvar->as);
2737ec681f3Smrg      if (gvar->constant)
2747ec681f3Smrg         _mesa_string_buffer_append(d->buf, "const ");
2757ec681f3Smrg      if (gvar->align)
2767ec681f3Smrg         _mesa_string_buffer_append(d->buf, "align ");
2777ec681f3Smrg      if (gvar->initializer)
2787ec681f3Smrg         _mesa_string_buffer_printf(d->buf, "init_id:%d\n", gvar->initializer->id);
2797ec681f3Smrg      dump_type_name(d, gvar->type);
2807ec681f3Smrg      _mesa_string_buffer_printf(d->buf, " val_id:%d\n", gvar->value.id);
2817ec681f3Smrg   }
2827ec681f3Smrg   dxil_dump_indention_dec(d);
2837ec681f3Smrg}
2847ec681f3Smrg
2857ec681f3Smrgstatic void
2867ec681f3Smrgdump_funcs(struct dxil_dumper *d, struct list_head *list)
2877ec681f3Smrg{
2887ec681f3Smrg   if (!list_length(list))
2897ec681f3Smrg      return;
2907ec681f3Smrg
2917ec681f3Smrg   _mesa_string_buffer_append(d->buf, "Functions:\n");
2927ec681f3Smrg   dxil_dump_indention_inc(d);
2937ec681f3Smrg   list_for_each_entry(struct dxil_func, func, list, head) {
2947ec681f3Smrg      dxil_dump_indent(d);
2957ec681f3Smrg      if (func->decl)
2967ec681f3Smrg         _mesa_string_buffer_append(d->buf, "declare ");
2977ec681f3Smrg      _mesa_string_buffer_append(d->buf, func->name);
2987ec681f3Smrg      _mesa_string_buffer_append_char(d->buf, ' ');
2997ec681f3Smrg      dump_type_name(d, func->type);
3007ec681f3Smrg      if (func->attr_set)
3017ec681f3Smrg         _mesa_string_buffer_printf(d->buf, " #%d", func->attr_set);
3027ec681f3Smrg      _mesa_string_buffer_append_char(d->buf, '\n');
3037ec681f3Smrg   }
3047ec681f3Smrg   dxil_dump_indention_dec(d);
3057ec681f3Smrg}
3067ec681f3Smrg
3077ec681f3Smrgstatic void
3087ec681f3Smrgdump_attr_set_list(struct dxil_dumper *d, struct list_head *list)
3097ec681f3Smrg{
3107ec681f3Smrg   if (!list_length(list))
3117ec681f3Smrg      return;
3127ec681f3Smrg
3137ec681f3Smrg   _mesa_string_buffer_append(d->buf, "Attribute set:\n");
3147ec681f3Smrg   dxil_dump_indention_inc(d);
3157ec681f3Smrg   int attr_id = 1;
3167ec681f3Smrg   list_for_each_entry(struct attrib_set, attr, list, head) {
3177ec681f3Smrg      _mesa_string_buffer_printf(d->buf, "  #%d: {", attr_id++);
3187ec681f3Smrg      for (unsigned i = 0; i < attr->num_attrs; ++i) {
3197ec681f3Smrg         if (i > 0)
3207ec681f3Smrg            _mesa_string_buffer_append_char(d->buf, ' ');
3217ec681f3Smrg
3227ec681f3Smrg         assert(attr->attrs[i].type == DXIL_ATTR_ENUM);
3237ec681f3Smrg         const char *value = "";
3247ec681f3Smrg         switch (attr->attrs[i].kind) {
3257ec681f3Smrg         case DXIL_ATTR_KIND_NONE: value = "none"; break;
3267ec681f3Smrg         case DXIL_ATTR_KIND_NO_UNWIND: value = "nounwind"; break;
3277ec681f3Smrg         case DXIL_ATTR_KIND_READ_NONE: value = "readnone"; break;
3287ec681f3Smrg         case DXIL_ATTR_KIND_READ_ONLY: value = "readonly"; break;
3297ec681f3Smrg         case DXIL_ATTR_KIND_NO_DUPLICATE: value = "noduplicate"; break;
3307ec681f3Smrg         }
3317ec681f3Smrg         _mesa_string_buffer_append(d->buf, value);
3327ec681f3Smrg      }
3337ec681f3Smrg      _mesa_string_buffer_append(d->buf, "}\n");
3347ec681f3Smrg   }
3357ec681f3Smrg   dxil_dump_indention_dec(d);
3367ec681f3Smrg}
3377ec681f3Smrg
3387ec681f3Smrgstatic void
3397ec681f3Smrgdump_constants(struct dxil_dumper *d, struct list_head *list)
3407ec681f3Smrg{
3417ec681f3Smrg   if (!list_length(list))
3427ec681f3Smrg      return;
3437ec681f3Smrg
3447ec681f3Smrg   _mesa_string_buffer_append(d->buf, "Constants:\n");
3457ec681f3Smrg   dxil_dump_indention_inc(d);
3467ec681f3Smrg   list_for_each_entry(struct dxil_const, cnst, list, head) {
3477ec681f3Smrg      _mesa_string_buffer_append_char(d->buf, ' ');
3487ec681f3Smrg      dump_value(d, &cnst->value);
3497ec681f3Smrg      _mesa_string_buffer_append(d->buf, " = ");
3507ec681f3Smrg      dump_type_name(d, cnst->value.type);
3517ec681f3Smrg      if (!cnst->undef) {
3527ec681f3Smrg         switch (cnst->value.type->type) {
3537ec681f3Smrg         case TYPE_FLOAT:
3547ec681f3Smrg            _mesa_string_buffer_printf(d->buf, " %10.5f\n", cnst->float_value);
3557ec681f3Smrg            break;
3567ec681f3Smrg         case TYPE_INTEGER:
3577ec681f3Smrg            _mesa_string_buffer_printf(d->buf, " %d\n", cnst->int_value);
3587ec681f3Smrg            break;
3597ec681f3Smrg         case TYPE_ARRAY:
3607ec681f3Smrg            _mesa_string_buffer_append(d->buf, "{");
3617ec681f3Smrg            for (unsigned i = 0;
3627ec681f3Smrg                 i < cnst->value.type->array_or_vector_def.num_elems; i++) {
3637ec681f3Smrg               _mesa_string_buffer_printf(d->buf, " %%%d",
3647ec681f3Smrg                                          cnst->array_values[i]->id);
3657ec681f3Smrg               dump_type_name(d, cnst->value.type);
3667ec681f3Smrg	       if (i != cnst->value.type->array_or_vector_def.num_elems - 1)
3677ec681f3Smrg                  _mesa_string_buffer_append(d->buf, ",");
3687ec681f3Smrg               _mesa_string_buffer_append(d->buf, " ");
3697ec681f3Smrg            }
3707ec681f3Smrg            _mesa_string_buffer_append(d->buf, "}\n");
3717ec681f3Smrg            break;
3727ec681f3Smrg         default:
3737ec681f3Smrg            unreachable("Unsupported const type");
3747ec681f3Smrg         }
3757ec681f3Smrg      } else
3767ec681f3Smrg         _mesa_string_buffer_append(d->buf, " undef\n");
3777ec681f3Smrg   }
3787ec681f3Smrg   dxil_dump_indention_dec(d);
3797ec681f3Smrg}
3807ec681f3Smrg
3817ec681f3Smrgstatic void
3827ec681f3Smrgdump_instrs(struct dxil_dumper *d, struct list_head *list)
3837ec681f3Smrg{
3847ec681f3Smrg   _mesa_string_buffer_append(d->buf, "Shader body:\n");
3857ec681f3Smrg   dxil_dump_indention_inc(d);
3867ec681f3Smrg
3877ec681f3Smrg   list_for_each_entry(struct dxil_instr, instr, list, head) {
3887ec681f3Smrg
3897ec681f3Smrg      dxil_dump_indent(d);
3907ec681f3Smrg      if (instr->has_value) {
3917ec681f3Smrg         dump_value(d, &instr->value);
3927ec681f3Smrg         _mesa_string_buffer_append(d->buf, " = ");
3937ec681f3Smrg      } else {
3947ec681f3Smrg         _mesa_string_buffer_append_char(d->buf, ' ');
3957ec681f3Smrg      }
3967ec681f3Smrg
3977ec681f3Smrg      switch (instr->type) {
3987ec681f3Smrg      case INSTR_BINOP: dump_instr_binop(d, &instr->binop); break;
3997ec681f3Smrg      case INSTR_CMP:   dump_instr_cmp(d, &instr->cmp);break;
4007ec681f3Smrg      case INSTR_SELECT:dump_instr_select(d, &instr->select); break;
4017ec681f3Smrg      case INSTR_CAST:  dump_instr_cast(d, &instr->cast); break;
4027ec681f3Smrg      case INSTR_CALL:  dump_instr_call(d, &instr->call); break;
4037ec681f3Smrg      case INSTR_RET:   dump_instr_ret(d, &instr->ret); break;
4047ec681f3Smrg      case INSTR_EXTRACTVAL: dump_instr_extractval(d, &instr->extractval); break;
4057ec681f3Smrg      case INSTR_BR:  dump_instr_branch(d, &instr->br); break;
4067ec681f3Smrg      case INSTR_PHI:  dump_instr_phi(d, &instr->phi); break;
4077ec681f3Smrg      case INSTR_ALLOCA: dump_instr_alloca(d, &instr->alloca); break;
4087ec681f3Smrg      case INSTR_GEP: dump_instr_gep(d, &instr->gep); break;
4097ec681f3Smrg      case INSTR_LOAD: dump_instr_load(d, &instr->load); break;
4107ec681f3Smrg      case INSTR_STORE: dump_instr_store(d, &instr->store); break;
4117ec681f3Smrg      case INSTR_ATOMICRMW: dump_instr_atomicrmw(d, &instr->atomicrmw); break;
4127ec681f3Smrg      default:
4137ec681f3Smrg         _mesa_string_buffer_printf(d->buf, "unknown instruction type %d", instr->type);
4147ec681f3Smrg      }
4157ec681f3Smrg
4167ec681f3Smrg      _mesa_string_buffer_append(d->buf, "\n");
4177ec681f3Smrg   }
4187ec681f3Smrg   dxil_dump_indention_dec(d);
4197ec681f3Smrg}
4207ec681f3Smrg
4217ec681f3Smrgstatic void
4227ec681f3Smrgdump_instr_binop(struct dxil_dumper *d, struct dxil_instr_binop *binop)
4237ec681f3Smrg{
4247ec681f3Smrg   const char *str = binop->opcode < DXIL_BINOP_INSTR_COUNT ?
4257ec681f3Smrg                        binop_strings[binop->opcode] : "INVALID";
4267ec681f3Smrg
4277ec681f3Smrg   _mesa_string_buffer_printf(d->buf, "%s ", str);
4287ec681f3Smrg   dump_instr_print_operands(d, 2, binop->operands);
4297ec681f3Smrg}
4307ec681f3Smrg
4317ec681f3Smrgstatic void
4327ec681f3Smrgdump_instr_cmp(struct dxil_dumper *d, struct dxil_instr_cmp *cmp)
4337ec681f3Smrg{
4347ec681f3Smrg   const char *str = cmp->pred < DXIL_CMP_INSTR_COUNT ?
4357ec681f3Smrg                        pred_strings[cmp->pred] : "INVALID";
4367ec681f3Smrg
4377ec681f3Smrg   _mesa_string_buffer_printf(d->buf, "%s ", str);
4387ec681f3Smrg   dump_instr_print_operands(d, 2, cmp->operands);
4397ec681f3Smrg}
4407ec681f3Smrg
4417ec681f3Smrgstatic void
4427ec681f3Smrgdump_instr_select(struct dxil_dumper *d, struct dxil_instr_select *select)
4437ec681f3Smrg{
4447ec681f3Smrg   _mesa_string_buffer_append(d->buf, "sel ");
4457ec681f3Smrg   dump_instr_print_operands(d, 3, select->operands);
4467ec681f3Smrg}
4477ec681f3Smrg
4487ec681f3Smrgstatic void
4497ec681f3Smrgdump_instr_cast(struct dxil_dumper *d, struct dxil_instr_cast *cast)
4507ec681f3Smrg{
4517ec681f3Smrg   const char *str = cast->opcode < DXIL_CAST_INSTR_COUNT ?
4527ec681f3Smrg                        cast_opcode_strings[cast->opcode] : "INVALID";
4537ec681f3Smrg
4547ec681f3Smrg   _mesa_string_buffer_printf(d->buf, "%s.", str);
4557ec681f3Smrg   dump_type_name(d, cast->type);
4567ec681f3Smrg   _mesa_string_buffer_append_char(d->buf, ' ');
4577ec681f3Smrg   dump_value(d, cast->value);
4587ec681f3Smrg}
4597ec681f3Smrg
4607ec681f3Smrgstatic void
4617ec681f3Smrgdump_instr_call(struct dxil_dumper *d, struct dxil_instr_call *call)
4627ec681f3Smrg{
4637ec681f3Smrg   assert(call->num_args == call->func->type->function_def.args.num_types);
4647ec681f3Smrg   struct dxil_type **func_arg_types = call->func->type->function_def.args.types;
4657ec681f3Smrg
4667ec681f3Smrg   _mesa_string_buffer_printf(d->buf, "%s(", call->func->name);
4677ec681f3Smrg   for (unsigned i = 0; i < call->num_args; ++i) {
4687ec681f3Smrg      if (i > 0)
4697ec681f3Smrg         _mesa_string_buffer_append(d->buf, ", ");
4707ec681f3Smrg      dump_type_name(d, func_arg_types[i]);
4717ec681f3Smrg      _mesa_string_buffer_append_char(d->buf, ' ');
4727ec681f3Smrg      dump_value(d, call->args[i]);
4737ec681f3Smrg   }
4747ec681f3Smrg   _mesa_string_buffer_append_char(d->buf, ')');
4757ec681f3Smrg}
4767ec681f3Smrg
4777ec681f3Smrgstatic void
4787ec681f3Smrgdump_instr_ret(struct dxil_dumper *d, struct dxil_instr_ret *ret)
4797ec681f3Smrg{
4807ec681f3Smrg   _mesa_string_buffer_append(d->buf, "ret ");
4817ec681f3Smrg   if (ret->value)
4827ec681f3Smrg      dump_value(d, ret->value);
4837ec681f3Smrg}
4847ec681f3Smrg
4857ec681f3Smrgstatic void
4867ec681f3Smrgdump_instr_extractval(struct dxil_dumper *d, struct dxil_instr_extractval *extr)
4877ec681f3Smrg{
4887ec681f3Smrg   _mesa_string_buffer_append(d->buf, "extractvalue ");
4897ec681f3Smrg   dump_type_name(d, extr->type);
4907ec681f3Smrg   dump_value(d, extr->src);
4917ec681f3Smrg   _mesa_string_buffer_printf(d->buf, ", %d", extr->idx);
4927ec681f3Smrg}
4937ec681f3Smrg
4947ec681f3Smrgstatic void
4957ec681f3Smrgdump_instr_branch(struct dxil_dumper *d, struct dxil_instr_br *br)
4967ec681f3Smrg{
4977ec681f3Smrg   _mesa_string_buffer_append(d->buf, "branch ");
4987ec681f3Smrg   if (br->cond)
4997ec681f3Smrg      dump_value(d, br->cond);
5007ec681f3Smrg   else
5017ec681f3Smrg      _mesa_string_buffer_append(d->buf, " (uncond)");
5027ec681f3Smrg   _mesa_string_buffer_printf(d->buf, " %d %d", br->succ[0], br->succ[1]);
5037ec681f3Smrg}
5047ec681f3Smrg
5057ec681f3Smrgstatic void
5067ec681f3Smrgdump_instr_phi(struct dxil_dumper *d, struct dxil_instr_phi *phi)
5077ec681f3Smrg{
5087ec681f3Smrg   _mesa_string_buffer_append(d->buf, "phi ");
5097ec681f3Smrg   dump_type_name(d, phi->type);
5107ec681f3Smrg   struct dxil_phi_src *src = phi->incoming;
5117ec681f3Smrg   for (unsigned i = 0; i < phi->num_incoming; ++i, ++src) {
5127ec681f3Smrg      if (i > 0)
5137ec681f3Smrg         _mesa_string_buffer_append(d->buf, ", ");
5147ec681f3Smrg      dump_value(d, src->value);
5157ec681f3Smrg      _mesa_string_buffer_printf(d->buf, "(%d)", src->block);
5167ec681f3Smrg   }
5177ec681f3Smrg}
5187ec681f3Smrg
5197ec681f3Smrgstatic void
5207ec681f3Smrgdump_instr_alloca(struct dxil_dumper *d, struct dxil_instr_alloca *alloca)
5217ec681f3Smrg{
5227ec681f3Smrg   _mesa_string_buffer_append(d->buf, "alloca ");
5237ec681f3Smrg   dump_type_name(d, alloca->alloc_type);
5247ec681f3Smrg   _mesa_string_buffer_append(d->buf, ", ");
5257ec681f3Smrg   dump_type_name(d, alloca->size_type);
5267ec681f3Smrg   _mesa_string_buffer_append(d->buf, ", ");
5277ec681f3Smrg   dump_value(d, alloca->size);
5287ec681f3Smrg   unsigned align_mask = (1 << 6 ) - 1;
5297ec681f3Smrg   unsigned align = alloca->align & align_mask;
5307ec681f3Smrg   _mesa_string_buffer_printf(d->buf, ", %d", 1 << (align - 1));
5317ec681f3Smrg}
5327ec681f3Smrg
5337ec681f3Smrgstatic void
5347ec681f3Smrgdump_instr_gep(struct dxil_dumper *d, struct dxil_instr_gep *gep)
5357ec681f3Smrg{
5367ec681f3Smrg   _mesa_string_buffer_append(d->buf, "getelementptr ");
5377ec681f3Smrg   if (gep->inbounds)
5387ec681f3Smrg      _mesa_string_buffer_append(d->buf, "inbounds ");
5397ec681f3Smrg   dump_type_name(d, gep->source_elem_type);
5407ec681f3Smrg   _mesa_string_buffer_append(d->buf, ", ");
5417ec681f3Smrg   for (unsigned i = 0; i < gep->num_operands; ++i) {
5427ec681f3Smrg      if (i > 0)
5437ec681f3Smrg         _mesa_string_buffer_append(d->buf, ", ");
5447ec681f3Smrg      dump_value(d, gep->operands[i]);
5457ec681f3Smrg   }
5467ec681f3Smrg}
5477ec681f3Smrg
5487ec681f3Smrgstatic void
5497ec681f3Smrgdump_instr_load(struct dxil_dumper *d, struct dxil_instr_load *load)
5507ec681f3Smrg{
5517ec681f3Smrg   _mesa_string_buffer_append(d->buf, "load ");
5527ec681f3Smrg   if (load->is_volatile)
5537ec681f3Smrg      _mesa_string_buffer_append(d->buf, " volatile");
5547ec681f3Smrg   dump_type_name(d, load->type);
5557ec681f3Smrg   _mesa_string_buffer_append(d->buf, ", ");
5567ec681f3Smrg   dump_value(d, load->ptr);
5577ec681f3Smrg   _mesa_string_buffer_printf(d->buf, ", %d", load->align);
5587ec681f3Smrg}
5597ec681f3Smrg
5607ec681f3Smrgstatic void
5617ec681f3Smrgdump_instr_store(struct dxil_dumper *d, struct dxil_instr_store *store)
5627ec681f3Smrg{
5637ec681f3Smrg   _mesa_string_buffer_append(d->buf, "store ");
5647ec681f3Smrg   if (store->is_volatile)
5657ec681f3Smrg      _mesa_string_buffer_append(d->buf, " volatile");
5667ec681f3Smrg   dump_value(d, store->value);
5677ec681f3Smrg   _mesa_string_buffer_append(d->buf, ", ");
5687ec681f3Smrg   dump_value(d, store->ptr);
5697ec681f3Smrg   _mesa_string_buffer_printf(d->buf, ", %d", store->align);
5707ec681f3Smrg}
5717ec681f3Smrg
5727ec681f3Smrgstatic const char *rmworder_str[] = {
5737ec681f3Smrg   [DXIL_ATOMIC_ORDERING_NOTATOMIC] = "not-atomic",
5747ec681f3Smrg   [DXIL_ATOMIC_ORDERING_UNORDERED] = "unordered",
5757ec681f3Smrg   [DXIL_ATOMIC_ORDERING_MONOTONIC] = "monotonic",
5767ec681f3Smrg   [DXIL_ATOMIC_ORDERING_ACQUIRE] = "acquire",
5777ec681f3Smrg   [DXIL_ATOMIC_ORDERING_RELEASE] = "release",
5787ec681f3Smrg   [DXIL_ATOMIC_ORDERING_ACQREL] = "acqrel",
5797ec681f3Smrg   [DXIL_ATOMIC_ORDERING_SEQCST] = "seqcst",
5807ec681f3Smrg};
5817ec681f3Smrg
5827ec681f3Smrgstatic const char *rmwsync_str[] = {
5837ec681f3Smrg   [DXIL_SYNC_SCOPE_SINGLETHREAD] = "single-thread",
5847ec681f3Smrg   [DXIL_SYNC_SCOPE_CROSSTHREAD] = "cross-thread",
5857ec681f3Smrg};
5867ec681f3Smrg
5877ec681f3Smrgstatic const char *rmwop_str[] = {
5887ec681f3Smrg   [DXIL_RMWOP_XCHG] = "xchg",
5897ec681f3Smrg   [DXIL_RMWOP_ADD] = "add",
5907ec681f3Smrg   [DXIL_RMWOP_SUB] = "sub",
5917ec681f3Smrg   [DXIL_RMWOP_AND] = "and",
5927ec681f3Smrg   [DXIL_RMWOP_NAND] = "nand",
5937ec681f3Smrg   [DXIL_RMWOP_OR] = "or",
5947ec681f3Smrg   [DXIL_RMWOP_XOR] = "xor",
5957ec681f3Smrg   [DXIL_RMWOP_MAX] = "max",
5967ec681f3Smrg   [DXIL_RMWOP_MIN] = "min",
5977ec681f3Smrg   [DXIL_RMWOP_UMAX] = "umax",
5987ec681f3Smrg   [DXIL_RMWOP_UMIN] = "umin",
5997ec681f3Smrg};
6007ec681f3Smrg
6017ec681f3Smrgstatic void
6027ec681f3Smrgdump_instr_atomicrmw(struct dxil_dumper *d, struct dxil_instr_atomicrmw *rmw)
6037ec681f3Smrg{
6047ec681f3Smrg   _mesa_string_buffer_printf(d->buf, "atomicrmw.%s ", rmwop_str[rmw->op]);
6057ec681f3Smrg
6067ec681f3Smrg   if (rmw->is_volatile)
6077ec681f3Smrg      _mesa_string_buffer_append(d->buf, " volatile");
6087ec681f3Smrg   dump_value(d, rmw->value);
6097ec681f3Smrg   _mesa_string_buffer_append(d->buf, ", ");
6107ec681f3Smrg   dump_value(d, rmw->ptr);
6117ec681f3Smrg   _mesa_string_buffer_printf(d->buf, ", ordering(%s)", rmworder_str[rmw->ordering]);
6127ec681f3Smrg   _mesa_string_buffer_printf(d->buf, ", sync_scope(%s)", rmwsync_str[rmw->syncscope]);
6137ec681f3Smrg}
6147ec681f3Smrg
6157ec681f3Smrgstatic void
6167ec681f3Smrgdump_instr_print_operands(struct dxil_dumper *d, int num,
6177ec681f3Smrg                          const struct dxil_value *val[])
6187ec681f3Smrg{
6197ec681f3Smrg   for (int i = 0; i < num; ++i) {
6207ec681f3Smrg      if (i > 0)
6217ec681f3Smrg         _mesa_string_buffer_append(d->buf, ", ");
6227ec681f3Smrg      dump_value(d, val[i]);
6237ec681f3Smrg   }
6247ec681f3Smrg}
6257ec681f3Smrg
6267ec681f3Smrgstatic void
6277ec681f3Smrgdump_value(struct dxil_dumper *d, const struct dxil_value *val)
6287ec681f3Smrg{
6297ec681f3Smrg   if (val->id < 10)
6307ec681f3Smrg      _mesa_string_buffer_append(d->buf, " ");
6317ec681f3Smrg   if (val->id < 100)
6327ec681f3Smrg      _mesa_string_buffer_append(d->buf, " ");
6337ec681f3Smrg   _mesa_string_buffer_printf(d->buf, "%%%d", val->id);
6347ec681f3Smrg  dump_type_name(d, val->type);
6357ec681f3Smrg}
6367ec681f3Smrg
6377ec681f3Smrgstatic void
6387ec681f3Smrgdump_mdnodes(struct dxil_dumper *d, struct list_head *list)
6397ec681f3Smrg{
6407ec681f3Smrg   if (!list_length(list))
6417ec681f3Smrg      return;
6427ec681f3Smrg
6437ec681f3Smrg   _mesa_string_buffer_append(d->buf, "MD-Nodes:\n");
6447ec681f3Smrg   dxil_dump_indention_inc(d);
6457ec681f3Smrg   list_for_each_entry(struct dxil_mdnode, node, list, head) {
6467ec681f3Smrg      dump_mdnode(d, node);
6477ec681f3Smrg   }
6487ec681f3Smrg   dxil_dump_indention_dec(d);
6497ec681f3Smrg}
6507ec681f3Smrg
6517ec681f3Smrgstatic void
6527ec681f3Smrgdump_mdnode(struct dxil_dumper *d, const struct dxil_mdnode *node)
6537ec681f3Smrg{
6547ec681f3Smrg   dxil_dump_indent(d);
6557ec681f3Smrg   switch (node->type) {
6567ec681f3Smrg   case MD_STRING:
6577ec681f3Smrg      _mesa_string_buffer_printf(d->buf, "S:%s\n", node->string);
6587ec681f3Smrg      break;
6597ec681f3Smrg   case MD_VALUE:
6607ec681f3Smrg      _mesa_string_buffer_append(d->buf, "V:");
6617ec681f3Smrg      dump_type_name(d, node->value.type);
6627ec681f3Smrg      _mesa_string_buffer_append_char(d->buf, ' ');
6637ec681f3Smrg      dump_value(d, node->value.value);
6647ec681f3Smrg      _mesa_string_buffer_append_char(d->buf, '\n');
6657ec681f3Smrg      break;
6667ec681f3Smrg   case MD_NODE:
6677ec681f3Smrg      _mesa_string_buffer_append(d->buf, " \\\n");
6687ec681f3Smrg      dxil_dump_indention_inc(d);
6697ec681f3Smrg      for (size_t i = 0; i < node->node.num_subnodes; ++i) {
6707ec681f3Smrg         if (node->node.subnodes[i])
6717ec681f3Smrg            dump_mdnode(d, node->node.subnodes[i]);
6727ec681f3Smrg         else {
6737ec681f3Smrg            dxil_dump_indent(d);
6747ec681f3Smrg            _mesa_string_buffer_append(d->buf, "(nullptr)\n");
6757ec681f3Smrg         }
6767ec681f3Smrg      }
6777ec681f3Smrg      dxil_dump_indention_dec(d);
6787ec681f3Smrg      break;
6797ec681f3Smrg   }
6807ec681f3Smrg}
6817ec681f3Smrg
6827ec681f3Smrgstatic void
6837ec681f3Smrgdump_named_nodes(struct dxil_dumper *d, struct list_head *list)
6847ec681f3Smrg{
6857ec681f3Smrg   if (!list_length(list))
6867ec681f3Smrg      return;
6877ec681f3Smrg
6887ec681f3Smrg   _mesa_string_buffer_append(d->buf, "Named Nodes:\n");
6897ec681f3Smrg   dxil_dump_indention_inc(d);
6907ec681f3Smrg   list_for_each_entry(struct dxil_named_node, node, list, head) {
6917ec681f3Smrg      dxil_dump_indent(d);
6927ec681f3Smrg      _mesa_string_buffer_printf(d->buf, "%s:\n", node->name);
6937ec681f3Smrg      dxil_dump_indention_inc(d);
6947ec681f3Smrg      for (size_t i = 0; i < node->num_subnodes; ++i) {
6957ec681f3Smrg         if (node->subnodes[i])
6967ec681f3Smrg            dump_mdnode(d, node->subnodes[i]);
6977ec681f3Smrg         else {
6987ec681f3Smrg            dxil_dump_indent(d);
6997ec681f3Smrg            _mesa_string_buffer_append(d->buf, "(nullptr)\n");
7007ec681f3Smrg         }
7017ec681f3Smrg      }
7027ec681f3Smrg      dxil_dump_indention_dec(d);
7037ec681f3Smrg   }
7047ec681f3Smrg   dxil_dump_indention_dec(d);
7057ec681f3Smrg}
7067ec681f3Smrg
7077ec681f3Smrgstatic void
7087ec681f3Smrgmask_to_string(uint32_t mask, char str[5])
7097ec681f3Smrg{
7107ec681f3Smrg   const char *mc = "xyzw";
7117ec681f3Smrg   for (int i = 0; i < 4 && mask; ++i) {
7127ec681f3Smrg      str[i] = (mask & (1 << i)) ? mc[i] : '_';
7137ec681f3Smrg   }
7147ec681f3Smrg   str[4] = 0;
7157ec681f3Smrg}
7167ec681f3Smrg
7177ec681f3Smrgstatic void dump_io_signatures(struct _mesa_string_buffer *buf, struct dxil_module *m)
7187ec681f3Smrg{
7197ec681f3Smrg   _mesa_string_buffer_append(buf, "\nInput signature:\n");
7207ec681f3Smrg   dump_io_signature(buf, m->num_sig_inputs, m->inputs);
7217ec681f3Smrg   _mesa_string_buffer_append(buf, "\nOutput signature:\n");
7227ec681f3Smrg   dump_io_signature(buf, m->num_sig_outputs, m->outputs);
7237ec681f3Smrg}
7247ec681f3Smrg
7257ec681f3Smrgstatic void dump_io_signature(struct _mesa_string_buffer *buf, unsigned num,
7267ec681f3Smrg                              struct dxil_signature_record *io)
7277ec681f3Smrg{
7287ec681f3Smrg   _mesa_string_buffer_append(buf, " SEMANTIC-NAME Index Mask Reg SysValue Format\n");
7297ec681f3Smrg   _mesa_string_buffer_append(buf, "----------------------------------------------\n");
7307ec681f3Smrg   for (unsigned i = 0; i < num; ++i, ++io)  {
7317ec681f3Smrg      for (unsigned j = 0; j < io->num_elements; ++j) {
7327ec681f3Smrg         char mask[5] = "";
7337ec681f3Smrg         mask_to_string(io->elements[j].mask, mask);
7347ec681f3Smrg         _mesa_string_buffer_printf(buf, "%-15s %3d %4s %3d %-8s %-7s\n",
7357ec681f3Smrg                                    io->name, io->elements[j].semantic_index,
7367ec681f3Smrg                                    mask, io->elements[j].reg, io->sysvalue,
7377ec681f3Smrg                                    component_type_as_string(io->elements[j].comp_type));
7387ec681f3Smrg      }
7397ec681f3Smrg   }
7407ec681f3Smrg}
7417ec681f3Smrg
7427ec681f3Smrgstatic const char *component_type_as_string(uint32_t type)
7437ec681f3Smrg{
7447ec681f3Smrg   return  (type < DXIL_PROG_SIG_COMP_TYPE_COUNT) ?
7457ec681f3Smrg            dxil_type_strings[type] : "invalid";
7467ec681f3Smrg}
7477ec681f3Smrg
7487ec681f3Smrgstatic void dump_psv(struct _mesa_string_buffer *buf,
7497ec681f3Smrg                     struct dxil_module *m)
7507ec681f3Smrg{
7517ec681f3Smrg   _mesa_string_buffer_append(buf, "\nPipeline State Validation\nInputs:\n");
7527ec681f3Smrg   dump_psv_io(buf, m, m->num_sig_inputs, m->psv_inputs);
7537ec681f3Smrg   _mesa_string_buffer_append(buf, "\nOutputs:\n");
7547ec681f3Smrg   dump_psv_io(buf, m, m->num_sig_outputs, m->psv_outputs);
7557ec681f3Smrg}
7567ec681f3Smrg
7577ec681f3Smrgstatic void dump_psv_io(struct _mesa_string_buffer *buf, struct dxil_module *m,
7587ec681f3Smrg                        unsigned num, struct dxil_psv_signature_element *io)
7597ec681f3Smrg{
7607ec681f3Smrg   _mesa_string_buffer_append(buf, " SEMANTIC-NAME Rows Cols Kind Comp-Type Interp dynmask+stream Indices\n");
7617ec681f3Smrg   _mesa_string_buffer_append(buf, "----------------------------------------------\n");
7627ec681f3Smrg   for (unsigned  i = 0; i < num; ++i, ++io)  {
7637ec681f3Smrg      _mesa_string_buffer_printf(buf, "%-14s %d+%d  %d+%d %4d   %-7s    %-4d        %-9d [",
7647ec681f3Smrg              m->sem_string_table->buf + io->semantic_name_offset,
7657ec681f3Smrg              (int)io->start_row, (int)io->rows,
7667ec681f3Smrg              (int)((io->cols_and_start & 0xf) >> 4),
7677ec681f3Smrg              (int)(io->cols_and_start & 0xf),
7687ec681f3Smrg              (int)io->semantic_kind,
7697ec681f3Smrg              component_type_as_string(io->component_type),
7707ec681f3Smrg              (int)io->interpolation_mode,
7717ec681f3Smrg              (int)io->dynamic_mask_and_stream);
7727ec681f3Smrg      for (int k = 0; k < io->rows; ++k) {
7737ec681f3Smrg         if (k > 0)
7747ec681f3Smrg            _mesa_string_buffer_append(buf, ", ");
7757ec681f3Smrg         _mesa_string_buffer_printf(buf,"%d ", m->sem_index_table.data[io->start_row  + k]);
7767ec681f3Smrg      }
7777ec681f3Smrg      _mesa_string_buffer_append(buf, "]\n");
7787ec681f3Smrg   }
7797ec681f3Smrg}
780