14a49301eSmrg/**************************************************************************
24a49301eSmrg *
3af69d88dSmrg * Copyright 2007-2008 VMware, Inc.
44a49301eSmrg * All Rights Reserved.
54a49301eSmrg *
64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a
74a49301eSmrg * copy of this software and associated documentation files (the
84a49301eSmrg * "Software"), to deal in the Software without restriction, including
94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish,
104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to
114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to
124a49301eSmrg * the following conditions:
134a49301eSmrg *
144a49301eSmrg * The above copyright notice and this permission notice (including the
154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions
164a49301eSmrg * of the Software.
174a49301eSmrg *
184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
254a49301eSmrg *
264a49301eSmrg **************************************************************************/
274a49301eSmrg
2801e04c3fSmrg#include <inttypes.h>
2901e04c3fSmrg
304a49301eSmrg#include "util/u_debug.h"
314a49301eSmrg#include "util/u_string.h"
324a49301eSmrg#include "util/u_math.h"
334a49301eSmrg#include "util/u_memory.h"
3401e04c3fSmrg#include "util/u_math.h"
354a49301eSmrg#include "tgsi_dump.h"
364a49301eSmrg#include "tgsi_info.h"
374a49301eSmrg#include "tgsi_iterate.h"
38af69d88dSmrg#include "tgsi_strings.h"
394a49301eSmrg
404a49301eSmrg
414a49301eSmrg/** Number of spaces to indent for IF/LOOP/etc */
424a49301eSmrgstatic const int indent_spaces = 3;
434a49301eSmrg
444a49301eSmrg
454a49301eSmrgstruct dump_ctx
464a49301eSmrg{
474a49301eSmrg   struct tgsi_iterate_context iter;
484a49301eSmrg
4901e04c3fSmrg   boolean dump_float_as_hex;
5001e04c3fSmrg
514a49301eSmrg   uint instno;
52af69d88dSmrg   uint immno;
534a49301eSmrg   int indent;
544a49301eSmrg
554a49301eSmrg   uint indentation;
5601e04c3fSmrg   FILE *file;
574a49301eSmrg
58af69d88dSmrg   void (*dump_printf)(struct dump_ctx *ctx, const char *format, ...);
594a49301eSmrg};
604a49301eSmrg
614a49301eSmrgstatic void
624a49301eSmrgdump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
634a49301eSmrg{
644a49301eSmrg   va_list ap;
654a49301eSmrg   (void)ctx;
664a49301eSmrg   va_start(ap, format);
6701e04c3fSmrg   if (ctx->file)
6801e04c3fSmrg      vfprintf(ctx->file, format, ap);
6901e04c3fSmrg   else
7001e04c3fSmrg      _debug_vprintf(format, ap);
714a49301eSmrg   va_end(ap);
724a49301eSmrg}
734a49301eSmrg
744a49301eSmrgstatic void
754a49301eSmrgdump_enum(
764a49301eSmrg   struct dump_ctx *ctx,
774a49301eSmrg   uint e,
784a49301eSmrg   const char **enums,
794a49301eSmrg   uint enum_count )
804a49301eSmrg{
814a49301eSmrg   if (e >= enum_count)
82af69d88dSmrg      ctx->dump_printf( ctx, "%u", e );
834a49301eSmrg   else
84af69d88dSmrg      ctx->dump_printf( ctx, "%s", enums[e] );
854a49301eSmrg}
864a49301eSmrg
87af69d88dSmrg#define EOL()           ctx->dump_printf( ctx, "\n" )
88af69d88dSmrg#define TXT(S)          ctx->dump_printf( ctx, "%s", S )
89af69d88dSmrg#define CHR(C)          ctx->dump_printf( ctx, "%c", C )
90af69d88dSmrg#define UIX(I)          ctx->dump_printf( ctx, "0x%x", I )
91af69d88dSmrg#define UID(I)          ctx->dump_printf( ctx, "%u", I )
9201e04c3fSmrg#define SI64D(I)        ctx->dump_printf( ctx, "%"PRId64, I )
9301e04c3fSmrg#define UI64D(I)        ctx->dump_printf( ctx, "%"PRIu64, I )
94af69d88dSmrg#define INSTID(I)       ctx->dump_printf( ctx, "% 3u", I )
95af69d88dSmrg#define SID(I)          ctx->dump_printf( ctx, "%d", I )
96af69d88dSmrg#define FLT(F)          ctx->dump_printf( ctx, "%10.4f", F )
9701e04c3fSmrg#define DBL(D)          ctx->dump_printf( ctx, "%10.8f", D )
9801e04c3fSmrg#define HFLT(F)         ctx->dump_printf( ctx, "0x%08x", fui((F)) )
994a49301eSmrg#define ENM(E,ENUMS)    dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
1004a49301eSmrg
1013464ebd5Sriastradhconst char *
1023464ebd5Sriastradhtgsi_swizzle_names[4] =
1034a49301eSmrg{
1044a49301eSmrg   "x",
1054a49301eSmrg   "y",
1064a49301eSmrg   "z",
1074a49301eSmrg   "w"
1084a49301eSmrg};
1094a49301eSmrg
110cdc920a0Smrgstatic void
111cdc920a0Smrg_dump_register_src(
112cdc920a0Smrg   struct dump_ctx *ctx,
113cdc920a0Smrg   const struct tgsi_full_src_register *src )
114cdc920a0Smrg{
115af69d88dSmrg   TXT(tgsi_file_name(src->Register.File));
116cdc920a0Smrg   if (src->Register.Dimension) {
1173464ebd5Sriastradh      if (src->Dimension.Indirect) {
1183464ebd5Sriastradh         CHR( '[' );
119af69d88dSmrg         TXT(tgsi_file_name(src->DimIndirect.File));
1203464ebd5Sriastradh         CHR( '[' );
1213464ebd5Sriastradh         SID( src->DimIndirect.Index );
1223464ebd5Sriastradh         TXT( "]." );
123af69d88dSmrg         ENM( src->DimIndirect.Swizzle, tgsi_swizzle_names );
1243464ebd5Sriastradh         if (src->Dimension.Index != 0) {
1253464ebd5Sriastradh            if (src->Dimension.Index > 0)
1263464ebd5Sriastradh               CHR( '+' );
1273464ebd5Sriastradh            SID( src->Dimension.Index );
1283464ebd5Sriastradh         }
1293464ebd5Sriastradh         CHR( ']' );
130af69d88dSmrg         if (src->DimIndirect.ArrayID) {
131af69d88dSmrg            CHR( '(' );
132af69d88dSmrg            SID( src->DimIndirect.ArrayID );
133af69d88dSmrg            CHR( ')' );
134af69d88dSmrg         }
1353464ebd5Sriastradh      } else {
1363464ebd5Sriastradh         CHR('[');
1373464ebd5Sriastradh         SID(src->Dimension.Index);
1383464ebd5Sriastradh         CHR(']');
1393464ebd5Sriastradh      }
140cdc920a0Smrg   }
141cdc920a0Smrg   if (src->Register.Indirect) {
142cdc920a0Smrg      CHR( '[' );
143af69d88dSmrg      TXT(tgsi_file_name(src->Indirect.File));
144cdc920a0Smrg      CHR( '[' );
145cdc920a0Smrg      SID( src->Indirect.Index );
146cdc920a0Smrg      TXT( "]." );
147af69d88dSmrg      ENM( src->Indirect.Swizzle, tgsi_swizzle_names );
148cdc920a0Smrg      if (src->Register.Index != 0) {
149cdc920a0Smrg         if (src->Register.Index > 0)
150cdc920a0Smrg            CHR( '+' );
151cdc920a0Smrg         SID( src->Register.Index );
152cdc920a0Smrg      }
153cdc920a0Smrg      CHR( ']' );
154af69d88dSmrg      if (src->Indirect.ArrayID) {
155af69d88dSmrg         CHR( '(' );
156af69d88dSmrg         SID( src->Indirect.ArrayID );
157af69d88dSmrg         CHR( ')' );
158af69d88dSmrg      }
159cdc920a0Smrg   } else {
160cdc920a0Smrg      CHR( '[' );
161cdc920a0Smrg      SID( src->Register.Index );
162cdc920a0Smrg      CHR( ']' );
163cdc920a0Smrg   }
164cdc920a0Smrg}
165cdc920a0Smrg
1663464ebd5Sriastradh
1674a49301eSmrgstatic void
1683464ebd5Sriastradh_dump_register_dst(
1694a49301eSmrg   struct dump_ctx *ctx,
1703464ebd5Sriastradh   const struct tgsi_full_dst_register *dst )
1714a49301eSmrg{
172af69d88dSmrg   TXT(tgsi_file_name(dst->Register.File));
1733464ebd5Sriastradh   if (dst->Register.Dimension) {
1743464ebd5Sriastradh      if (dst->Dimension.Indirect) {
1753464ebd5Sriastradh         CHR( '[' );
176af69d88dSmrg         TXT(tgsi_file_name(dst->DimIndirect.File));
1773464ebd5Sriastradh         CHR( '[' );
1783464ebd5Sriastradh         SID( dst->DimIndirect.Index );
1793464ebd5Sriastradh         TXT( "]." );
180af69d88dSmrg         ENM( dst->DimIndirect.Swizzle, tgsi_swizzle_names );
1813464ebd5Sriastradh         if (dst->Dimension.Index != 0) {
1823464ebd5Sriastradh            if (dst->Dimension.Index > 0)
1833464ebd5Sriastradh               CHR( '+' );
1843464ebd5Sriastradh            SID( dst->Dimension.Index );
1853464ebd5Sriastradh         }
1863464ebd5Sriastradh         CHR( ']' );
187af69d88dSmrg         if (dst->DimIndirect.ArrayID) {
188af69d88dSmrg            CHR( '(' );
189af69d88dSmrg            SID( dst->DimIndirect.ArrayID );
190af69d88dSmrg            CHR( ')' );
191af69d88dSmrg         }
1923464ebd5Sriastradh      } else {
1933464ebd5Sriastradh         CHR('[');
1943464ebd5Sriastradh         SID(dst->Dimension.Index);
1953464ebd5Sriastradh         CHR(']');
1963464ebd5Sriastradh      }
1973464ebd5Sriastradh   }
1983464ebd5Sriastradh   if (dst->Register.Indirect) {
1993464ebd5Sriastradh      CHR( '[' );
200af69d88dSmrg      TXT(tgsi_file_name(dst->Indirect.File));
2013464ebd5Sriastradh      CHR( '[' );
2023464ebd5Sriastradh      SID( dst->Indirect.Index );
2033464ebd5Sriastradh      TXT( "]." );
204af69d88dSmrg      ENM( dst->Indirect.Swizzle, tgsi_swizzle_names );
2053464ebd5Sriastradh      if (dst->Register.Index != 0) {
2063464ebd5Sriastradh         if (dst->Register.Index > 0)
2073464ebd5Sriastradh            CHR( '+' );
2083464ebd5Sriastradh         SID( dst->Register.Index );
2093464ebd5Sriastradh      }
2103464ebd5Sriastradh      CHR( ']' );
211af69d88dSmrg      if (dst->Indirect.ArrayID) {
212af69d88dSmrg         CHR( '(' );
213af69d88dSmrg         SID( dst->Indirect.ArrayID );
214af69d88dSmrg         CHR( ')' );
215af69d88dSmrg      }
2163464ebd5Sriastradh   } else {
2173464ebd5Sriastradh      CHR( '[' );
2183464ebd5Sriastradh      SID( dst->Register.Index );
2193464ebd5Sriastradh      CHR( ']' );
2204a49301eSmrg   }
2214a49301eSmrg}
2224a49301eSmrgstatic void
2234a49301eSmrg_dump_writemask(
2244a49301eSmrg   struct dump_ctx *ctx,
2254a49301eSmrg   uint writemask )
2264a49301eSmrg{
2274a49301eSmrg   if (writemask != TGSI_WRITEMASK_XYZW) {
2284a49301eSmrg      CHR( '.' );
2294a49301eSmrg      if (writemask & TGSI_WRITEMASK_X)
2304a49301eSmrg         CHR( 'x' );
2314a49301eSmrg      if (writemask & TGSI_WRITEMASK_Y)
2324a49301eSmrg         CHR( 'y' );
2334a49301eSmrg      if (writemask & TGSI_WRITEMASK_Z)
2344a49301eSmrg         CHR( 'z' );
2354a49301eSmrg      if (writemask & TGSI_WRITEMASK_W)
2364a49301eSmrg         CHR( 'w' );
2374a49301eSmrg   }
2384a49301eSmrg}
2394a49301eSmrg
2403464ebd5Sriastradhstatic void
2413464ebd5Sriastradhdump_imm_data(struct tgsi_iterate_context *iter,
2423464ebd5Sriastradh              union tgsi_immediate_data *data,
2433464ebd5Sriastradh              unsigned num_tokens,
2443464ebd5Sriastradh              unsigned data_type)
2453464ebd5Sriastradh{
2463464ebd5Sriastradh   struct dump_ctx *ctx = (struct dump_ctx *)iter;
2473464ebd5Sriastradh   unsigned i ;
2483464ebd5Sriastradh
2493464ebd5Sriastradh   TXT( " {" );
2503464ebd5Sriastradh
2513464ebd5Sriastradh   assert( num_tokens <= 4 );
2523464ebd5Sriastradh   for (i = 0; i < num_tokens; i++) {
2533464ebd5Sriastradh      switch (data_type) {
25401e04c3fSmrg      case TGSI_IMM_FLOAT64: {
25501e04c3fSmrg         union di d;
25601e04c3fSmrg         d.ui = data[i].Uint | (uint64_t)data[i+1].Uint << 32;
25701e04c3fSmrg         DBL( d.d );
25801e04c3fSmrg         i++;
25901e04c3fSmrg         break;
26001e04c3fSmrg      }
26101e04c3fSmrg      case TGSI_IMM_INT64: {
26201e04c3fSmrg         union di d;
26301e04c3fSmrg         d.i = data[i].Uint | (uint64_t)data[i+1].Uint << 32;
26401e04c3fSmrg         SI64D( d.i );
26501e04c3fSmrg         i++;
26601e04c3fSmrg         break;
26701e04c3fSmrg      }
26801e04c3fSmrg      case TGSI_IMM_UINT64: {
26901e04c3fSmrg         union di d;
27001e04c3fSmrg         d.ui = data[i].Uint | (uint64_t)data[i+1].Uint << 32;
27101e04c3fSmrg         UI64D( d.ui );
27201e04c3fSmrg         i++;
27301e04c3fSmrg         break;
27401e04c3fSmrg      }
2753464ebd5Sriastradh      case TGSI_IMM_FLOAT32:
27601e04c3fSmrg         if (ctx->dump_float_as_hex)
27701e04c3fSmrg            HFLT( data[i].Float );
27801e04c3fSmrg         else
27901e04c3fSmrg            FLT( data[i].Float );
2803464ebd5Sriastradh         break;
2813464ebd5Sriastradh      case TGSI_IMM_UINT32:
2823464ebd5Sriastradh         UID(data[i].Uint);
2833464ebd5Sriastradh         break;
2843464ebd5Sriastradh      case TGSI_IMM_INT32:
2853464ebd5Sriastradh         SID(data[i].Int);
2863464ebd5Sriastradh         break;
2873464ebd5Sriastradh      default:
2883464ebd5Sriastradh         assert( 0 );
2893464ebd5Sriastradh      }
2903464ebd5Sriastradh
2913464ebd5Sriastradh      if (i < num_tokens - 1)
2923464ebd5Sriastradh         TXT( ", " );
2933464ebd5Sriastradh   }
2943464ebd5Sriastradh   TXT( "}" );
2953464ebd5Sriastradh}
2963464ebd5Sriastradh
2974a49301eSmrgstatic boolean
2984a49301eSmrgiter_declaration(
2994a49301eSmrg   struct tgsi_iterate_context *iter,
3004a49301eSmrg   struct tgsi_full_declaration *decl )
3014a49301eSmrg{
3024a49301eSmrg   struct dump_ctx *ctx = (struct dump_ctx *)iter;
30301e04c3fSmrg   boolean patch = decl->Semantic.Name == TGSI_SEMANTIC_PATCH ||
30401e04c3fSmrg      decl->Semantic.Name == TGSI_SEMANTIC_TESSINNER ||
30501e04c3fSmrg      decl->Semantic.Name == TGSI_SEMANTIC_TESSOUTER ||
30601e04c3fSmrg      decl->Semantic.Name == TGSI_SEMANTIC_PRIMID;
3074a49301eSmrg
3084a49301eSmrg   TXT( "DCL " );
3094a49301eSmrg
310af69d88dSmrg   TXT(tgsi_file_name(decl->Declaration.File));
311cdc920a0Smrg
31201e04c3fSmrg   /* all geometry shader inputs and non-patch tessellation shader inputs are
31301e04c3fSmrg    * two dimensional
31401e04c3fSmrg    */
315cdc920a0Smrg   if (decl->Declaration.File == TGSI_FILE_INPUT &&
31601e04c3fSmrg       (iter->processor.Processor == PIPE_SHADER_GEOMETRY ||
31701e04c3fSmrg        (!patch &&
31801e04c3fSmrg         (iter->processor.Processor == PIPE_SHADER_TESS_CTRL ||
31901e04c3fSmrg          iter->processor.Processor == PIPE_SHADER_TESS_EVAL)))) {
32001e04c3fSmrg      TXT("[]");
32101e04c3fSmrg   }
32201e04c3fSmrg
32301e04c3fSmrg   /* all non-patch tess ctrl shader outputs are two dimensional */
32401e04c3fSmrg   if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
32501e04c3fSmrg       !patch &&
32601e04c3fSmrg       iter->processor.Processor == PIPE_SHADER_TESS_CTRL) {
327cdc920a0Smrg      TXT("[]");
328cdc920a0Smrg   }
329cdc920a0Smrg
330cdc920a0Smrg   if (decl->Declaration.Dimension) {
331cdc920a0Smrg      CHR('[');
332cdc920a0Smrg      SID(decl->Dim.Index2D);
333cdc920a0Smrg      CHR(']');
334cdc920a0Smrg   }
335cdc920a0Smrg
336cdc920a0Smrg   CHR('[');
337cdc920a0Smrg   SID(decl->Range.First);
338cdc920a0Smrg   if (decl->Range.First != decl->Range.Last) {
339cdc920a0Smrg      TXT("..");
340cdc920a0Smrg      SID(decl->Range.Last);
341cdc920a0Smrg   }
342cdc920a0Smrg   CHR(']');
343cdc920a0Smrg
3444a49301eSmrg   _dump_writemask(
3454a49301eSmrg      ctx,
3464a49301eSmrg      decl->Declaration.UsageMask );
3474a49301eSmrg
348af69d88dSmrg   if (decl->Declaration.Array) {
349af69d88dSmrg      TXT( ", ARRAY(" );
350af69d88dSmrg      SID(decl->Array.ArrayID);
351af69d88dSmrg      CHR(')');
352af69d88dSmrg   }
353af69d88dSmrg
354af69d88dSmrg   if (decl->Declaration.Local)
355af69d88dSmrg      TXT( ", LOCAL" );
356af69d88dSmrg
3574a49301eSmrg   if (decl->Declaration.Semantic) {
3584a49301eSmrg      TXT( ", " );
359af69d88dSmrg      ENM( decl->Semantic.Name, tgsi_semantic_names );
360cdc920a0Smrg      if (decl->Semantic.Index != 0 ||
361af69d88dSmrg          decl->Semantic.Name == TGSI_SEMANTIC_TEXCOORD ||
362cdc920a0Smrg          decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) {
3634a49301eSmrg         CHR( '[' );
364cdc920a0Smrg         UID( decl->Semantic.Index );
3654a49301eSmrg         CHR( ']' );
3664a49301eSmrg      }
36701e04c3fSmrg
36801e04c3fSmrg      if (decl->Semantic.StreamX != 0 || decl->Semantic.StreamY != 0 ||
36901e04c3fSmrg          decl->Semantic.StreamZ != 0 || decl->Semantic.StreamW != 0) {
37001e04c3fSmrg         TXT(", STREAM(");
37101e04c3fSmrg         UID(decl->Semantic.StreamX);
37201e04c3fSmrg         TXT(", ");
37301e04c3fSmrg         UID(decl->Semantic.StreamY);
37401e04c3fSmrg         TXT(", ");
37501e04c3fSmrg         UID(decl->Semantic.StreamZ);
37601e04c3fSmrg         TXT(", ");
37701e04c3fSmrg         UID(decl->Semantic.StreamW);
37801e04c3fSmrg         CHR(')');
37901e04c3fSmrg      }
3804a49301eSmrg   }
3814a49301eSmrg
38201e04c3fSmrg   if (decl->Declaration.File == TGSI_FILE_IMAGE) {
38301e04c3fSmrg      TXT(", ");
38401e04c3fSmrg      ENM(decl->Image.Resource, tgsi_texture_names);
3853464ebd5Sriastradh      TXT(", ");
38601e04c3fSmrg      TXT(util_format_name(decl->Image.Format));
38701e04c3fSmrg      if (decl->Image.Writable)
388af69d88dSmrg         TXT(", WR");
38901e04c3fSmrg      if (decl->Image.Raw)
390af69d88dSmrg         TXT(", RAW");
391af69d88dSmrg   }
392af69d88dSmrg
39301e04c3fSmrg   if (decl->Declaration.File == TGSI_FILE_BUFFER) {
39401e04c3fSmrg      if (decl->Declaration.Atomic)
39501e04c3fSmrg         TXT(", ATOMIC");
39601e04c3fSmrg   }
39701e04c3fSmrg
39801e04c3fSmrg   if (decl->Declaration.File == TGSI_FILE_MEMORY) {
39901e04c3fSmrg      switch (decl->Declaration.MemType) {
40001e04c3fSmrg      /* Note: ,GLOBAL is optional / the default */
40101e04c3fSmrg      case TGSI_MEMORY_TYPE_GLOBAL:  TXT(", GLOBAL");  break;
40201e04c3fSmrg      case TGSI_MEMORY_TYPE_SHARED:  TXT(", SHARED");  break;
40301e04c3fSmrg      case TGSI_MEMORY_TYPE_PRIVATE: TXT(", PRIVATE"); break;
40401e04c3fSmrg      case TGSI_MEMORY_TYPE_INPUT:   TXT(", INPUT");   break;
40501e04c3fSmrg      }
40601e04c3fSmrg   }
40701e04c3fSmrg
408af69d88dSmrg   if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
409af69d88dSmrg      TXT(", ");
410af69d88dSmrg      ENM(decl->SamplerView.Resource, tgsi_texture_names);
4113464ebd5Sriastradh      TXT(", ");
412af69d88dSmrg      if ((decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeY) &&
413af69d88dSmrg          (decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeZ) &&
414af69d88dSmrg          (decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeW)) {
41501e04c3fSmrg         ENM(decl->SamplerView.ReturnTypeX, tgsi_return_type_names);
4163464ebd5Sriastradh      } else {
41701e04c3fSmrg         ENM(decl->SamplerView.ReturnTypeX, tgsi_return_type_names);
4183464ebd5Sriastradh         TXT(", ");
41901e04c3fSmrg         ENM(decl->SamplerView.ReturnTypeY, tgsi_return_type_names);
4203464ebd5Sriastradh         TXT(", ");
42101e04c3fSmrg         ENM(decl->SamplerView.ReturnTypeZ, tgsi_return_type_names);
4223464ebd5Sriastradh         TXT(", ");
42301e04c3fSmrg         ENM(decl->SamplerView.ReturnTypeW, tgsi_return_type_names);
4243464ebd5Sriastradh      }
4254a49301eSmrg   }
4264a49301eSmrg
427af69d88dSmrg   if (decl->Declaration.Interpolate) {
42801e04c3fSmrg      if (iter->processor.Processor == PIPE_SHADER_FRAGMENT &&
429af69d88dSmrg          decl->Declaration.File == TGSI_FILE_INPUT)
430af69d88dSmrg      {
431af69d88dSmrg         TXT( ", " );
432af69d88dSmrg         ENM( decl->Interp.Interpolate, tgsi_interpolate_names );
433cdc920a0Smrg      }
434cdc920a0Smrg
435af69d88dSmrg      if (decl->Interp.Location != TGSI_INTERPOLATE_LOC_CENTER) {
436af69d88dSmrg         TXT( ", " );
437af69d88dSmrg         ENM( decl->Interp.Location, tgsi_interpolate_locations );
4383464ebd5Sriastradh      }
439af69d88dSmrg   }
4403464ebd5Sriastradh
441af69d88dSmrg   if (decl->Declaration.Invariant) {
442af69d88dSmrg      TXT( ", INVARIANT" );
4433464ebd5Sriastradh   }
4443464ebd5Sriastradh
4454a49301eSmrg   EOL();
4464a49301eSmrg
4474a49301eSmrg   return TRUE;
4484a49301eSmrg}
4494a49301eSmrg
4504a49301eSmrgvoid
4514a49301eSmrgtgsi_dump_declaration(
4524a49301eSmrg   const struct tgsi_full_declaration *decl )
4534a49301eSmrg{
4544a49301eSmrg   struct dump_ctx ctx;
45501e04c3fSmrg   memset(&ctx, 0, sizeof(ctx));
4564a49301eSmrg
457af69d88dSmrg   ctx.dump_printf = dump_ctx_printf;
4584a49301eSmrg
4594a49301eSmrg   iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
4604a49301eSmrg}
4614a49301eSmrg
462cdc920a0Smrgstatic boolean
463cdc920a0Smrgiter_property(
464cdc920a0Smrg   struct tgsi_iterate_context *iter,
465cdc920a0Smrg   struct tgsi_full_property *prop )
466cdc920a0Smrg{
46701e04c3fSmrg   int i;
468cdc920a0Smrg   struct dump_ctx *ctx = (struct dump_ctx *)iter;
469cdc920a0Smrg
470cdc920a0Smrg   TXT( "PROPERTY " );
4713464ebd5Sriastradh   ENM(prop->Property.PropertyName, tgsi_property_names);
472cdc920a0Smrg
473cdc920a0Smrg   if (prop->Property.NrTokens > 1)
474cdc920a0Smrg      TXT(" ");
475cdc920a0Smrg
476cdc920a0Smrg   for (i = 0; i < prop->Property.NrTokens - 1; ++i) {
477cdc920a0Smrg      switch (prop->Property.PropertyName) {
478cdc920a0Smrg      case TGSI_PROPERTY_GS_INPUT_PRIM:
479cdc920a0Smrg      case TGSI_PROPERTY_GS_OUTPUT_PRIM:
4803464ebd5Sriastradh         ENM(prop->u[i].Data, tgsi_primitive_names);
481cdc920a0Smrg         break;
482cdc920a0Smrg      case TGSI_PROPERTY_FS_COORD_ORIGIN:
4833464ebd5Sriastradh         ENM(prop->u[i].Data, tgsi_fs_coord_origin_names);
484cdc920a0Smrg         break;
485cdc920a0Smrg      case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
4863464ebd5Sriastradh         ENM(prop->u[i].Data, tgsi_fs_coord_pixel_center_names);
487cdc920a0Smrg         break;
48801e04c3fSmrg      case TGSI_PROPERTY_NEXT_SHADER:
48901e04c3fSmrg         ENM(prop->u[i].Data, tgsi_processor_type_names);
49001e04c3fSmrg         break;
491cdc920a0Smrg      default:
492cdc920a0Smrg         SID( prop->u[i].Data );
493cdc920a0Smrg         break;
494cdc920a0Smrg      }
495cdc920a0Smrg      if (i < prop->Property.NrTokens - 2)
496cdc920a0Smrg         TXT( ", " );
497cdc920a0Smrg   }
498cdc920a0Smrg   EOL();
499cdc920a0Smrg
500cdc920a0Smrg   return TRUE;
501cdc920a0Smrg}
502cdc920a0Smrg
503cdc920a0Smrgvoid tgsi_dump_property(
504cdc920a0Smrg   const struct tgsi_full_property *prop )
505cdc920a0Smrg{
506cdc920a0Smrg   struct dump_ctx ctx;
50701e04c3fSmrg   memset(&ctx, 0, sizeof(ctx));
508cdc920a0Smrg
509af69d88dSmrg   ctx.dump_printf = dump_ctx_printf;
510cdc920a0Smrg
511cdc920a0Smrg   iter_property( &ctx.iter, (struct tgsi_full_property *)prop );
512cdc920a0Smrg}
513cdc920a0Smrg
5144a49301eSmrgstatic boolean
5154a49301eSmrgiter_immediate(
5164a49301eSmrg   struct tgsi_iterate_context *iter,
5174a49301eSmrg   struct tgsi_full_immediate *imm )
5184a49301eSmrg{
5194a49301eSmrg   struct dump_ctx *ctx = (struct dump_ctx *) iter;
5204a49301eSmrg
521af69d88dSmrg   TXT( "IMM[" );
522af69d88dSmrg   SID( ctx->immno++ );
523af69d88dSmrg   TXT( "] " );
524af69d88dSmrg   ENM( imm->Immediate.DataType, tgsi_immediate_type_names );
5254a49301eSmrg
5263464ebd5Sriastradh   dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1,
5273464ebd5Sriastradh                 imm->Immediate.DataType);
5284a49301eSmrg
5294a49301eSmrg   EOL();
5304a49301eSmrg
5314a49301eSmrg   return TRUE;
5324a49301eSmrg}
5334a49301eSmrg
5344a49301eSmrgvoid
5354a49301eSmrgtgsi_dump_immediate(
5364a49301eSmrg   const struct tgsi_full_immediate *imm )
5374a49301eSmrg{
5384a49301eSmrg   struct dump_ctx ctx;
53901e04c3fSmrg   memset(&ctx, 0, sizeof(ctx));
5404a49301eSmrg
541af69d88dSmrg   ctx.dump_printf = dump_ctx_printf;
5424a49301eSmrg
5434a49301eSmrg   iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
5444a49301eSmrg}
5454a49301eSmrg
5464a49301eSmrgstatic boolean
5474a49301eSmrgiter_instruction(
5484a49301eSmrg   struct tgsi_iterate_context *iter,
5494a49301eSmrg   struct tgsi_full_instruction *inst )
5504a49301eSmrg{
5514a49301eSmrg   struct dump_ctx *ctx = (struct dump_ctx *) iter;
5524a49301eSmrg   uint instno = ctx->instno++;
5534a49301eSmrg   const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
5544a49301eSmrg   uint i;
5554a49301eSmrg   boolean first_reg = TRUE;
5564a49301eSmrg
5574a49301eSmrg   INSTID( instno );
5584a49301eSmrg   TXT( ": " );
5593464ebd5Sriastradh
5604a49301eSmrg   ctx->indent -= info->pre_dedent;
5614a49301eSmrg   for(i = 0; (int)i < ctx->indent; ++i)
5624a49301eSmrg      TXT( "  " );
5634a49301eSmrg   ctx->indent += info->post_indent;
5643464ebd5Sriastradh
56501e04c3fSmrg   TXT( tgsi_get_opcode_name(inst->Instruction.Opcode) );
5663464ebd5Sriastradh
56701e04c3fSmrg   if (inst->Instruction.Saturate) {
56801e04c3fSmrg      TXT( "_SAT" );
5693464ebd5Sriastradh   }
5703464ebd5Sriastradh
57101e04c3fSmrg   if (inst->Instruction.Precise) {
57201e04c3fSmrg      TXT( "_PRECISE" );
5734a49301eSmrg   }
5744a49301eSmrg
5754a49301eSmrg   for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
576cdc920a0Smrg      const struct tgsi_full_dst_register *dst = &inst->Dst[i];
5774a49301eSmrg
5784a49301eSmrg      if (!first_reg)
5794a49301eSmrg         CHR( ',' );
5804a49301eSmrg      CHR( ' ' );
5814a49301eSmrg
5823464ebd5Sriastradh      _dump_register_dst( ctx, dst );
583cdc920a0Smrg      _dump_writemask( ctx, dst->Register.WriteMask );
5844a49301eSmrg
5854a49301eSmrg      first_reg = FALSE;
5864a49301eSmrg   }
5874a49301eSmrg
5884a49301eSmrg   for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
589cdc920a0Smrg      const struct tgsi_full_src_register *src = &inst->Src[i];
5904a49301eSmrg
5914a49301eSmrg      if (!first_reg)
5924a49301eSmrg         CHR( ',' );
5934a49301eSmrg      CHR( ' ' );
5944a49301eSmrg
595cdc920a0Smrg      if (src->Register.Negate)
5964a49301eSmrg         CHR( '-' );
597cdc920a0Smrg      if (src->Register.Absolute)
598cdc920a0Smrg         CHR( '|' );
5994a49301eSmrg
600cdc920a0Smrg      _dump_register_src(ctx, src);
6014a49301eSmrg
602cdc920a0Smrg      if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
603cdc920a0Smrg          src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
604cdc920a0Smrg          src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
605cdc920a0Smrg          src->Register.SwizzleW != TGSI_SWIZZLE_W) {
6064a49301eSmrg         CHR( '.' );
6073464ebd5Sriastradh         ENM( src->Register.SwizzleX, tgsi_swizzle_names );
6083464ebd5Sriastradh         ENM( src->Register.SwizzleY, tgsi_swizzle_names );
6093464ebd5Sriastradh         ENM( src->Register.SwizzleZ, tgsi_swizzle_names );
6103464ebd5Sriastradh         ENM( src->Register.SwizzleW, tgsi_swizzle_names );
6114a49301eSmrg      }
6124a49301eSmrg
613cdc920a0Smrg      if (src->Register.Absolute)
6144a49301eSmrg         CHR( '|' );
6154a49301eSmrg
6164a49301eSmrg      first_reg = FALSE;
6174a49301eSmrg   }
6184a49301eSmrg
619cdc920a0Smrg   if (inst->Instruction.Texture) {
62001e04c3fSmrg      if (!(inst->Instruction.Opcode >= TGSI_OPCODE_SAMPLE &&
62101e04c3fSmrg            inst->Instruction.Opcode <= TGSI_OPCODE_GATHER4)) {
62201e04c3fSmrg         TXT( ", " );
62301e04c3fSmrg         ENM( inst->Texture.Texture, tgsi_texture_names );
62401e04c3fSmrg      }
625af69d88dSmrg      for (i = 0; i < inst->Texture.NumOffsets; i++) {
626af69d88dSmrg         TXT( ", " );
627af69d88dSmrg         TXT(tgsi_file_name(inst->TexOffsets[i].File));
628af69d88dSmrg         CHR( '[' );
629af69d88dSmrg         SID( inst->TexOffsets[i].Index );
630af69d88dSmrg         CHR( ']' );
631af69d88dSmrg         CHR( '.' );
632af69d88dSmrg         ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names);
633af69d88dSmrg         ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names);
634af69d88dSmrg         ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names);
635af69d88dSmrg      }
6364a49301eSmrg   }
6374a49301eSmrg
63801e04c3fSmrg   if (inst->Instruction.Memory) {
63901e04c3fSmrg      uint32_t qualifier = inst->Memory.Qualifier;
64001e04c3fSmrg      while (qualifier) {
64101e04c3fSmrg         int bit = ffs(qualifier) - 1;
64201e04c3fSmrg         qualifier &= ~(1U << bit);
64301e04c3fSmrg         TXT(", ");
64401e04c3fSmrg         ENM(bit, tgsi_memory_names);
64501e04c3fSmrg      }
64601e04c3fSmrg      if (inst->Memory.Texture) {
64701e04c3fSmrg         TXT( ", " );
64801e04c3fSmrg         ENM( inst->Memory.Texture, tgsi_texture_names );
64901e04c3fSmrg      }
65001e04c3fSmrg      if (inst->Memory.Format) {
65101e04c3fSmrg         TXT( ", " );
65201e04c3fSmrg         TXT( util_format_name(inst->Memory.Format) );
65301e04c3fSmrg      }
65401e04c3fSmrg   }
65501e04c3fSmrg
65601e04c3fSmrg   if (inst->Instruction.Label) {
65701e04c3fSmrg      switch (inst->Instruction.Opcode) {
65801e04c3fSmrg      case TGSI_OPCODE_IF:
65901e04c3fSmrg      case TGSI_OPCODE_UIF:
66001e04c3fSmrg      case TGSI_OPCODE_ELSE:
66101e04c3fSmrg      case TGSI_OPCODE_BGNLOOP:
66201e04c3fSmrg      case TGSI_OPCODE_ENDLOOP:
66301e04c3fSmrg      case TGSI_OPCODE_CAL:
66401e04c3fSmrg      case TGSI_OPCODE_BGNSUB:
66501e04c3fSmrg         TXT( " :" );
66601e04c3fSmrg         UID( inst->Label.Label );
66701e04c3fSmrg         break;
66801e04c3fSmrg      }
6694a49301eSmrg   }
6704a49301eSmrg
6714a49301eSmrg   /* update indentation */
6724a49301eSmrg   if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
673af69d88dSmrg       inst->Instruction.Opcode == TGSI_OPCODE_UIF ||
6744a49301eSmrg       inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
6754a49301eSmrg       inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
6764a49301eSmrg      ctx->indentation += indent_spaces;
6774a49301eSmrg   }
6784a49301eSmrg
6794a49301eSmrg   EOL();
6804a49301eSmrg
6814a49301eSmrg   return TRUE;
6824a49301eSmrg}
6834a49301eSmrg
6844a49301eSmrgvoid
6854a49301eSmrgtgsi_dump_instruction(
6864a49301eSmrg   const struct tgsi_full_instruction *inst,
6874a49301eSmrg   uint instno )
6884a49301eSmrg{
6894a49301eSmrg   struct dump_ctx ctx;
69001e04c3fSmrg   memset(&ctx, 0, sizeof(ctx));
6914a49301eSmrg
6924a49301eSmrg   ctx.instno = instno;
693af69d88dSmrg   ctx.immno = instno;
6944a49301eSmrg   ctx.indent = 0;
695af69d88dSmrg   ctx.dump_printf = dump_ctx_printf;
6964a49301eSmrg   ctx.indentation = 0;
69701e04c3fSmrg   ctx.file = NULL;
6984a49301eSmrg
6994a49301eSmrg   iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
7004a49301eSmrg}
7014a49301eSmrg
7024a49301eSmrgstatic boolean
7034a49301eSmrgprolog(
7044a49301eSmrg   struct tgsi_iterate_context *iter )
7054a49301eSmrg{
7064a49301eSmrg   struct dump_ctx *ctx = (struct dump_ctx *) iter;
707af69d88dSmrg   ENM( iter->processor.Processor, tgsi_processor_type_names );
7084a49301eSmrg   EOL();
7094a49301eSmrg   return TRUE;
7104a49301eSmrg}
7114a49301eSmrg
71201e04c3fSmrgstatic void
71301e04c3fSmrginit_dump_ctx(struct dump_ctx *ctx, uint flags)
71401e04c3fSmrg{
71501e04c3fSmrg   memset(ctx, 0, sizeof(*ctx));
71601e04c3fSmrg
71701e04c3fSmrg   ctx->iter.prolog = prolog;
71801e04c3fSmrg   ctx->iter.iterate_instruction = iter_instruction;
71901e04c3fSmrg   ctx->iter.iterate_declaration = iter_declaration;
72001e04c3fSmrg   ctx->iter.iterate_immediate = iter_immediate;
72101e04c3fSmrg   ctx->iter.iterate_property = iter_property;
72201e04c3fSmrg
72301e04c3fSmrg   if (flags & TGSI_DUMP_FLOAT_AS_HEX)
72401e04c3fSmrg      ctx->dump_float_as_hex = TRUE;
72501e04c3fSmrg}
72601e04c3fSmrg
7274a49301eSmrgvoid
72801e04c3fSmrgtgsi_dump_to_file(const struct tgsi_token *tokens, uint flags, FILE *file)
7294a49301eSmrg{
7304a49301eSmrg   struct dump_ctx ctx;
73101e04c3fSmrg   memset(&ctx, 0, sizeof(ctx));
7324a49301eSmrg
73301e04c3fSmrg   init_dump_ctx(&ctx, flags);
7344a49301eSmrg
735af69d88dSmrg   ctx.dump_printf = dump_ctx_printf;
73601e04c3fSmrg   ctx.file = file;
7374a49301eSmrg
7384a49301eSmrg   tgsi_iterate_shader( tokens, &ctx.iter );
7394a49301eSmrg}
7404a49301eSmrg
74101e04c3fSmrgvoid
74201e04c3fSmrgtgsi_dump(const struct tgsi_token *tokens, uint flags)
74301e04c3fSmrg{
74401e04c3fSmrg   tgsi_dump_to_file(tokens, flags, NULL);
74501e04c3fSmrg}
74601e04c3fSmrg
7474a49301eSmrgstruct str_dump_ctx
7484a49301eSmrg{
7494a49301eSmrg   struct dump_ctx base;
7504a49301eSmrg   char *str;
7514a49301eSmrg   char *ptr;
7524a49301eSmrg   int left;
75301e04c3fSmrg   bool nospace;
7544a49301eSmrg};
7554a49301eSmrg
7564a49301eSmrgstatic void
7574a49301eSmrgstr_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
7584a49301eSmrg{
7594a49301eSmrg   struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
7604a49301eSmrg
76101e04c3fSmrg   if (!sctx->nospace) {
7624a49301eSmrg      int written;
7634a49301eSmrg      va_list ap;
7644a49301eSmrg      va_start(ap, format);
7657ec681f3Smrg      written = vsnprintf(sctx->ptr, sctx->left, format, ap);
7664a49301eSmrg      va_end(ap);
7674a49301eSmrg
7684a49301eSmrg      /* Some complicated logic needed to handle the return value of
7694a49301eSmrg       * vsnprintf:
7704a49301eSmrg       */
7714a49301eSmrg      if (written > 0) {
77201e04c3fSmrg         if (written >= sctx->left) {
77301e04c3fSmrg            sctx->nospace = true;
77401e04c3fSmrg            written = sctx->left;
77501e04c3fSmrg         }
7764a49301eSmrg         sctx->ptr += written;
7774a49301eSmrg         sctx->left -= written;
7784a49301eSmrg      }
7794a49301eSmrg   }
7804a49301eSmrg}
7814a49301eSmrg
78201e04c3fSmrgbool
7834a49301eSmrgtgsi_dump_str(
7844a49301eSmrg   const struct tgsi_token *tokens,
7854a49301eSmrg   uint flags,
7864a49301eSmrg   char *str,
7874a49301eSmrg   size_t size)
7884a49301eSmrg{
7894a49301eSmrg   struct str_dump_ctx ctx;
79001e04c3fSmrg   memset(&ctx, 0, sizeof(ctx));
7914a49301eSmrg
79201e04c3fSmrg   init_dump_ctx(&ctx.base, flags);
7934a49301eSmrg
794af69d88dSmrg   ctx.base.dump_printf = &str_dump_ctx_printf;
7954a49301eSmrg
7964a49301eSmrg   ctx.str = str;
7974a49301eSmrg   ctx.str[0] = 0;
7984a49301eSmrg   ctx.ptr = str;
7994a49301eSmrg   ctx.left = (int)size;
80001e04c3fSmrg   ctx.nospace = false;
8014a49301eSmrg
8024a49301eSmrg   tgsi_iterate_shader( tokens, &ctx.base.iter );
80301e04c3fSmrg
80401e04c3fSmrg   return !ctx.nospace;
8054a49301eSmrg}
806af69d88dSmrg
807af69d88dSmrgvoid
808af69d88dSmrgtgsi_dump_instruction_str(
809af69d88dSmrg   const struct tgsi_full_instruction *inst,
810af69d88dSmrg   uint instno,
811af69d88dSmrg   char *str,
812af69d88dSmrg   size_t size)
813af69d88dSmrg{
814af69d88dSmrg   struct str_dump_ctx ctx;
81501e04c3fSmrg   memset(&ctx, 0, sizeof(ctx));
816af69d88dSmrg
817af69d88dSmrg   ctx.base.instno = instno;
818af69d88dSmrg   ctx.base.immno = instno;
819af69d88dSmrg   ctx.base.indent = 0;
820af69d88dSmrg   ctx.base.dump_printf = &str_dump_ctx_printf;
821af69d88dSmrg   ctx.base.indentation = 0;
82201e04c3fSmrg   ctx.base.file = NULL;
823af69d88dSmrg
824af69d88dSmrg   ctx.str = str;
825af69d88dSmrg   ctx.str[0] = 0;
826af69d88dSmrg   ctx.ptr = str;
827af69d88dSmrg   ctx.left = (int)size;
82801e04c3fSmrg   ctx.nospace = false;
829af69d88dSmrg
830af69d88dSmrg   iter_instruction( &ctx.base.iter, (struct tgsi_full_instruction *)inst );
831af69d88dSmrg}
832