tgsi_dump.c revision a29e40a42382630c2d9d95d3a1e03a7b3db87add
1/**************************************************************************
2 *
3 * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "util/u_debug.h"
29#include "util/u_string.h"
30#include "util/u_math.h"
31#include "util/u_memory.h"
32#include "tgsi_dump.h"
33#include "tgsi_info.h"
34#include "tgsi_iterate.h"
35#include "tgsi_strings.h"
36
37
38/** Number of spaces to indent for IF/LOOP/etc */
39static const int indent_spaces = 3;
40
41
42struct dump_ctx
43{
44   struct tgsi_iterate_context iter;
45
46   uint instno;
47   uint immno;
48   int indent;
49
50   uint indentation;
51
52   void (*dump_printf)(struct dump_ctx *ctx, const char *format, ...);
53};
54
55static void
56dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
57{
58   va_list ap;
59   (void)ctx;
60   va_start(ap, format);
61   _debug_vprintf(format, ap);
62   va_end(ap);
63}
64
65static void
66dump_enum(
67   struct dump_ctx *ctx,
68   uint e,
69   const char **enums,
70   uint enum_count )
71{
72   if (e >= enum_count)
73      ctx->dump_printf( ctx, "%u", e );
74   else
75      ctx->dump_printf( ctx, "%s", enums[e] );
76}
77
78#define EOL()           ctx->dump_printf( ctx, "\n" )
79#define TXT(S)          ctx->dump_printf( ctx, "%s", S )
80#define CHR(C)          ctx->dump_printf( ctx, "%c", C )
81#define UIX(I)          ctx->dump_printf( ctx, "0x%x", I )
82#define UID(I)          ctx->dump_printf( ctx, "%u", I )
83#define INSTID(I)       ctx->dump_printf( ctx, "% 3u", I )
84#define SID(I)          ctx->dump_printf( ctx, "%d", I )
85#define FLT(F)          ctx->dump_printf( ctx, "%10.4f", F )
86#define ENM(E,ENUMS)    dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
87
88const char *
89tgsi_swizzle_names[4] =
90{
91   "x",
92   "y",
93   "z",
94   "w"
95};
96
97static void
98_dump_register_src(
99   struct dump_ctx *ctx,
100   const struct tgsi_full_src_register *src )
101{
102   TXT(tgsi_file_name(src->Register.File));
103   if (src->Register.Dimension) {
104      if (src->Dimension.Indirect) {
105         CHR( '[' );
106         TXT(tgsi_file_name(src->DimIndirect.File));
107         CHR( '[' );
108         SID( src->DimIndirect.Index );
109         TXT( "]." );
110         ENM( src->DimIndirect.Swizzle, tgsi_swizzle_names );
111         if (src->Dimension.Index != 0) {
112            if (src->Dimension.Index > 0)
113               CHR( '+' );
114            SID( src->Dimension.Index );
115         }
116         CHR( ']' );
117         if (src->DimIndirect.ArrayID) {
118            CHR( '(' );
119            SID( src->DimIndirect.ArrayID );
120            CHR( ')' );
121         }
122      } else {
123         CHR('[');
124         SID(src->Dimension.Index);
125         CHR(']');
126      }
127   }
128   if (src->Register.Indirect) {
129      CHR( '[' );
130      TXT(tgsi_file_name(src->Indirect.File));
131      CHR( '[' );
132      SID( src->Indirect.Index );
133      TXT( "]." );
134      ENM( src->Indirect.Swizzle, tgsi_swizzle_names );
135      if (src->Register.Index != 0) {
136         if (src->Register.Index > 0)
137            CHR( '+' );
138         SID( src->Register.Index );
139      }
140      CHR( ']' );
141      if (src->Indirect.ArrayID) {
142         CHR( '(' );
143         SID( src->Indirect.ArrayID );
144         CHR( ')' );
145      }
146   } else {
147      CHR( '[' );
148      SID( src->Register.Index );
149      CHR( ']' );
150   }
151}
152
153
154static void
155_dump_register_dst(
156   struct dump_ctx *ctx,
157   const struct tgsi_full_dst_register *dst )
158{
159   TXT(tgsi_file_name(dst->Register.File));
160   if (dst->Register.Dimension) {
161      if (dst->Dimension.Indirect) {
162         CHR( '[' );
163         TXT(tgsi_file_name(dst->DimIndirect.File));
164         CHR( '[' );
165         SID( dst->DimIndirect.Index );
166         TXT( "]." );
167         ENM( dst->DimIndirect.Swizzle, tgsi_swizzle_names );
168         if (dst->Dimension.Index != 0) {
169            if (dst->Dimension.Index > 0)
170               CHR( '+' );
171            SID( dst->Dimension.Index );
172         }
173         CHR( ']' );
174         if (dst->DimIndirect.ArrayID) {
175            CHR( '(' );
176            SID( dst->DimIndirect.ArrayID );
177            CHR( ')' );
178         }
179      } else {
180         CHR('[');
181         SID(dst->Dimension.Index);
182         CHR(']');
183      }
184   }
185   if (dst->Register.Indirect) {
186      CHR( '[' );
187      TXT(tgsi_file_name(dst->Indirect.File));
188      CHR( '[' );
189      SID( dst->Indirect.Index );
190      TXT( "]." );
191      ENM( dst->Indirect.Swizzle, tgsi_swizzle_names );
192      if (dst->Register.Index != 0) {
193         if (dst->Register.Index > 0)
194            CHR( '+' );
195         SID( dst->Register.Index );
196      }
197      CHR( ']' );
198      if (dst->Indirect.ArrayID) {
199         CHR( '(' );
200         SID( dst->Indirect.ArrayID );
201         CHR( ')' );
202      }
203   } else {
204      CHR( '[' );
205      SID( dst->Register.Index );
206      CHR( ']' );
207   }
208}
209static void
210_dump_writemask(
211   struct dump_ctx *ctx,
212   uint writemask )
213{
214   if (writemask != TGSI_WRITEMASK_XYZW) {
215      CHR( '.' );
216      if (writemask & TGSI_WRITEMASK_X)
217         CHR( 'x' );
218      if (writemask & TGSI_WRITEMASK_Y)
219         CHR( 'y' );
220      if (writemask & TGSI_WRITEMASK_Z)
221         CHR( 'z' );
222      if (writemask & TGSI_WRITEMASK_W)
223         CHR( 'w' );
224   }
225}
226
227static void
228dump_imm_data(struct tgsi_iterate_context *iter,
229              union tgsi_immediate_data *data,
230              unsigned num_tokens,
231              unsigned data_type)
232{
233   struct dump_ctx *ctx = (struct dump_ctx *)iter;
234   unsigned i ;
235
236   TXT( " {" );
237
238   assert( num_tokens <= 4 );
239   for (i = 0; i < num_tokens; i++) {
240      switch (data_type) {
241      case TGSI_IMM_FLOAT32:
242         FLT( data[i].Float );
243         break;
244      case TGSI_IMM_UINT32:
245         UID(data[i].Uint);
246         break;
247      case TGSI_IMM_INT32:
248         SID(data[i].Int);
249         break;
250      default:
251         assert( 0 );
252      }
253
254      if (i < num_tokens - 1)
255         TXT( ", " );
256   }
257   TXT( "}" );
258}
259
260static boolean
261iter_declaration(
262   struct tgsi_iterate_context *iter,
263   struct tgsi_full_declaration *decl )
264{
265   struct dump_ctx *ctx = (struct dump_ctx *)iter;
266
267   TXT( "DCL " );
268
269   TXT(tgsi_file_name(decl->Declaration.File));
270
271   /* all geometry shader inputs are two dimensional */
272   if (decl->Declaration.File == TGSI_FILE_INPUT &&
273       iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
274      TXT("[]");
275   }
276
277   if (decl->Declaration.Dimension) {
278      CHR('[');
279      SID(decl->Dim.Index2D);
280      CHR(']');
281   }
282
283   CHR('[');
284   SID(decl->Range.First);
285   if (decl->Range.First != decl->Range.Last) {
286      TXT("..");
287      SID(decl->Range.Last);
288   }
289   CHR(']');
290
291   _dump_writemask(
292      ctx,
293      decl->Declaration.UsageMask );
294
295   if (decl->Declaration.Array) {
296      TXT( ", ARRAY(" );
297      SID(decl->Array.ArrayID);
298      CHR(')');
299   }
300
301   if (decl->Declaration.Local)
302      TXT( ", LOCAL" );
303
304   if (decl->Declaration.Semantic) {
305      TXT( ", " );
306      ENM( decl->Semantic.Name, tgsi_semantic_names );
307      if (decl->Semantic.Index != 0 ||
308          decl->Semantic.Name == TGSI_SEMANTIC_TEXCOORD ||
309          decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) {
310         CHR( '[' );
311         UID( decl->Semantic.Index );
312         CHR( ']' );
313      }
314   }
315
316   if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
317      TXT(", ");
318      ENM(decl->Resource.Resource, tgsi_texture_names);
319      if (decl->Resource.Writable)
320         TXT(", WR");
321      if (decl->Resource.Raw)
322         TXT(", RAW");
323   }
324
325   if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
326      TXT(", ");
327      ENM(decl->SamplerView.Resource, tgsi_texture_names);
328      TXT(", ");
329      if ((decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeY) &&
330          (decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeZ) &&
331          (decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeW)) {
332         ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names);
333      } else {
334         ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names);
335         TXT(", ");
336         ENM(decl->SamplerView.ReturnTypeY, tgsi_type_names);
337         TXT(", ");
338         ENM(decl->SamplerView.ReturnTypeZ, tgsi_type_names);
339         TXT(", ");
340         ENM(decl->SamplerView.ReturnTypeW, tgsi_type_names);
341      }
342   }
343
344   if (decl->Declaration.Interpolate) {
345      if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
346          decl->Declaration.File == TGSI_FILE_INPUT)
347      {
348         TXT( ", " );
349         ENM( decl->Interp.Interpolate, tgsi_interpolate_names );
350      }
351
352      if (decl->Interp.Centroid) {
353         TXT( ", CENTROID" );
354      }
355
356      if (decl->Interp.CylindricalWrap) {
357         TXT(", CYLWRAP_");
358         if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_X) {
359            CHR('X');
360         }
361         if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Y) {
362            CHR('Y');
363         }
364         if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Z) {
365            CHR('Z');
366         }
367         if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_W) {
368            CHR('W');
369         }
370      }
371   }
372
373   if (decl->Declaration.Invariant) {
374      TXT( ", INVARIANT" );
375   }
376
377   EOL();
378
379   return TRUE;
380}
381
382void
383tgsi_dump_declaration(
384   const struct tgsi_full_declaration *decl )
385{
386   struct dump_ctx ctx;
387
388   ctx.dump_printf = dump_ctx_printf;
389
390   iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
391}
392
393static boolean
394iter_property(
395   struct tgsi_iterate_context *iter,
396   struct tgsi_full_property *prop )
397{
398   unsigned i;
399   struct dump_ctx *ctx = (struct dump_ctx *)iter;
400
401   TXT( "PROPERTY " );
402   ENM(prop->Property.PropertyName, tgsi_property_names);
403
404   if (prop->Property.NrTokens > 1)
405      TXT(" ");
406
407   for (i = 0; i < prop->Property.NrTokens - 1; ++i) {
408      switch (prop->Property.PropertyName) {
409      case TGSI_PROPERTY_GS_INPUT_PRIM:
410      case TGSI_PROPERTY_GS_OUTPUT_PRIM:
411         ENM(prop->u[i].Data, tgsi_primitive_names);
412         break;
413      case TGSI_PROPERTY_FS_COORD_ORIGIN:
414         ENM(prop->u[i].Data, tgsi_fs_coord_origin_names);
415         break;
416      case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
417         ENM(prop->u[i].Data, tgsi_fs_coord_pixel_center_names);
418         break;
419      default:
420         SID( prop->u[i].Data );
421         break;
422      }
423      if (i < prop->Property.NrTokens - 2)
424         TXT( ", " );
425   }
426   EOL();
427
428   return TRUE;
429}
430
431void tgsi_dump_property(
432   const struct tgsi_full_property *prop )
433{
434   struct dump_ctx ctx;
435
436   ctx.dump_printf = dump_ctx_printf;
437
438   iter_property( &ctx.iter, (struct tgsi_full_property *)prop );
439}
440
441static boolean
442iter_immediate(
443   struct tgsi_iterate_context *iter,
444   struct tgsi_full_immediate *imm )
445{
446   struct dump_ctx *ctx = (struct dump_ctx *) iter;
447
448   TXT( "IMM[" );
449   SID( ctx->immno++ );
450   TXT( "] " );
451   ENM( imm->Immediate.DataType, tgsi_immediate_type_names );
452
453   dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1,
454                 imm->Immediate.DataType);
455
456   EOL();
457
458   return TRUE;
459}
460
461void
462tgsi_dump_immediate(
463   const struct tgsi_full_immediate *imm )
464{
465   struct dump_ctx ctx;
466
467   ctx.dump_printf = dump_ctx_printf;
468
469   iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
470}
471
472static boolean
473iter_instruction(
474   struct tgsi_iterate_context *iter,
475   struct tgsi_full_instruction *inst )
476{
477   struct dump_ctx *ctx = (struct dump_ctx *) iter;
478   uint instno = ctx->instno++;
479   const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
480   uint i;
481   boolean first_reg = TRUE;
482
483   INSTID( instno );
484   TXT( ": " );
485
486   ctx->indent -= info->pre_dedent;
487   for(i = 0; (int)i < ctx->indent; ++i)
488      TXT( "  " );
489   ctx->indent += info->post_indent;
490
491   if (inst->Instruction.Predicate) {
492      CHR( '(' );
493
494      if (inst->Predicate.Negate)
495         CHR( '!' );
496
497      TXT( "PRED[" );
498      SID( inst->Predicate.Index );
499      CHR( ']' );
500
501      if (inst->Predicate.SwizzleX != TGSI_SWIZZLE_X ||
502          inst->Predicate.SwizzleY != TGSI_SWIZZLE_Y ||
503          inst->Predicate.SwizzleZ != TGSI_SWIZZLE_Z ||
504          inst->Predicate.SwizzleW != TGSI_SWIZZLE_W) {
505         CHR( '.' );
506         ENM( inst->Predicate.SwizzleX, tgsi_swizzle_names );
507         ENM( inst->Predicate.SwizzleY, tgsi_swizzle_names );
508         ENM( inst->Predicate.SwizzleZ, tgsi_swizzle_names );
509         ENM( inst->Predicate.SwizzleW, tgsi_swizzle_names );
510      }
511
512      TXT( ") " );
513   }
514
515   TXT( info->mnemonic );
516
517   switch (inst->Instruction.Saturate) {
518   case TGSI_SAT_NONE:
519      break;
520   case TGSI_SAT_ZERO_ONE:
521      TXT( "_SAT" );
522      break;
523   case TGSI_SAT_MINUS_PLUS_ONE:
524      TXT( "_SATNV" );
525      break;
526   default:
527      assert( 0 );
528   }
529
530   for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
531      const struct tgsi_full_dst_register *dst = &inst->Dst[i];
532
533      if (!first_reg)
534         CHR( ',' );
535      CHR( ' ' );
536
537      _dump_register_dst( ctx, dst );
538      _dump_writemask( ctx, dst->Register.WriteMask );
539
540      first_reg = FALSE;
541   }
542
543   for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
544      const struct tgsi_full_src_register *src = &inst->Src[i];
545
546      if (!first_reg)
547         CHR( ',' );
548      CHR( ' ' );
549
550      if (src->Register.Negate)
551         CHR( '-' );
552      if (src->Register.Absolute)
553         CHR( '|' );
554
555      _dump_register_src(ctx, src);
556
557      if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
558          src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
559          src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
560          src->Register.SwizzleW != TGSI_SWIZZLE_W) {
561         CHR( '.' );
562         ENM( src->Register.SwizzleX, tgsi_swizzle_names );
563         ENM( src->Register.SwizzleY, tgsi_swizzle_names );
564         ENM( src->Register.SwizzleZ, tgsi_swizzle_names );
565         ENM( src->Register.SwizzleW, tgsi_swizzle_names );
566      }
567
568      if (src->Register.Absolute)
569         CHR( '|' );
570
571      first_reg = FALSE;
572   }
573
574   if (inst->Instruction.Texture) {
575      TXT( ", " );
576      ENM( inst->Texture.Texture, tgsi_texture_names );
577      for (i = 0; i < inst->Texture.NumOffsets; i++) {
578         TXT( ", " );
579         TXT(tgsi_file_name(inst->TexOffsets[i].File));
580         CHR( '[' );
581         SID( inst->TexOffsets[i].Index );
582         CHR( ']' );
583         CHR( '.' );
584         ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names);
585         ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names);
586         ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names);
587      }
588   }
589
590   switch (inst->Instruction.Opcode) {
591   case TGSI_OPCODE_IF:
592   case TGSI_OPCODE_UIF:
593   case TGSI_OPCODE_ELSE:
594   case TGSI_OPCODE_BGNLOOP:
595   case TGSI_OPCODE_ENDLOOP:
596   case TGSI_OPCODE_CAL:
597      TXT( " :" );
598      UID( inst->Label.Label );
599      break;
600   }
601
602   /* update indentation */
603   if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
604       inst->Instruction.Opcode == TGSI_OPCODE_UIF ||
605       inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
606       inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
607      ctx->indentation += indent_spaces;
608   }
609
610   EOL();
611
612   return TRUE;
613}
614
615void
616tgsi_dump_instruction(
617   const struct tgsi_full_instruction *inst,
618   uint instno )
619{
620   struct dump_ctx ctx;
621
622   ctx.instno = instno;
623   ctx.immno = instno;
624   ctx.indent = 0;
625   ctx.dump_printf = dump_ctx_printf;
626   ctx.indentation = 0;
627
628   iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
629}
630
631static boolean
632prolog(
633   struct tgsi_iterate_context *iter )
634{
635   struct dump_ctx *ctx = (struct dump_ctx *) iter;
636   ENM( iter->processor.Processor, tgsi_processor_type_names );
637   EOL();
638   return TRUE;
639}
640
641void
642tgsi_dump(
643   const struct tgsi_token *tokens,
644   uint flags )
645{
646   struct dump_ctx ctx;
647
648   ctx.iter.prolog = prolog;
649   ctx.iter.iterate_instruction = iter_instruction;
650   ctx.iter.iterate_declaration = iter_declaration;
651   ctx.iter.iterate_immediate = iter_immediate;
652   ctx.iter.iterate_property = iter_property;
653   ctx.iter.epilog = NULL;
654
655   ctx.instno = 0;
656   ctx.immno = 0;
657   ctx.indent = 0;
658   ctx.dump_printf = dump_ctx_printf;
659   ctx.indentation = 0;
660
661   tgsi_iterate_shader( tokens, &ctx.iter );
662}
663
664struct str_dump_ctx
665{
666   struct dump_ctx base;
667   char *str;
668   char *ptr;
669   int left;
670};
671
672static void
673str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
674{
675   struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
676
677   if(sctx->left > 1) {
678      int written;
679      va_list ap;
680      va_start(ap, format);
681      written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
682      va_end(ap);
683
684      /* Some complicated logic needed to handle the return value of
685       * vsnprintf:
686       */
687      if (written > 0) {
688         written = MIN2(sctx->left, written);
689         sctx->ptr += written;
690         sctx->left -= written;
691      }
692   }
693}
694
695void
696tgsi_dump_str(
697   const struct tgsi_token *tokens,
698   uint flags,
699   char *str,
700   size_t size)
701{
702   struct str_dump_ctx ctx;
703
704   ctx.base.iter.prolog = prolog;
705   ctx.base.iter.iterate_instruction = iter_instruction;
706   ctx.base.iter.iterate_declaration = iter_declaration;
707   ctx.base.iter.iterate_immediate = iter_immediate;
708   ctx.base.iter.iterate_property = iter_property;
709   ctx.base.iter.epilog = NULL;
710
711   ctx.base.instno = 0;
712   ctx.base.immno = 0;
713   ctx.base.indent = 0;
714   ctx.base.dump_printf = &str_dump_ctx_printf;
715   ctx.base.indentation = 0;
716
717   ctx.str = str;
718   ctx.str[0] = 0;
719   ctx.ptr = str;
720   ctx.left = (int)size;
721
722   tgsi_iterate_shader( tokens, &ctx.base.iter );
723}
724
725void
726tgsi_dump_instruction_str(
727   const struct tgsi_full_instruction *inst,
728   uint instno,
729   char *str,
730   size_t size)
731{
732   struct str_dump_ctx ctx;
733
734   ctx.base.instno = instno;
735   ctx.base.immno = instno;
736   ctx.base.indent = 0;
737   ctx.base.dump_printf = &str_dump_ctx_printf;
738   ctx.base.indentation = 0;
739
740   ctx.str = str;
741   ctx.str[0] = 0;
742   ctx.ptr = str;
743   ctx.left = (int)size;
744
745   iter_instruction( &ctx.base.iter, (struct tgsi_full_instruction *)inst );
746}
747