• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2007-2008 VMware, Inc.
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 VMWARE 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 "util/u_math.h"
33 #include "tgsi_dump.h"
34 #include "tgsi_info.h"
35 #include "tgsi_iterate.h"
36 #include "tgsi_strings.h"
37 
38 
39 /** Number of spaces to indent for IF/LOOP/etc */
40 static const int indent_spaces = 3;
41 
42 
43 struct dump_ctx
44 {
45    struct tgsi_iterate_context iter;
46 
47    boolean dump_float_as_hex;
48 
49    uint instno;
50    uint immno;
51    int indent;
52 
53    uint indentation;
54    FILE *file;
55 
56    void (*dump_printf)(struct dump_ctx *ctx, const char *format, ...);
57 };
58 
59 static void
dump_ctx_printf(struct dump_ctx * ctx,const char * format,...)60 dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
61 {
62    va_list ap;
63    (void)ctx;
64    va_start(ap, format);
65    if (ctx->file)
66       vfprintf(ctx->file, format, ap);
67    else
68       _debug_vprintf(format, ap);
69    va_end(ap);
70 }
71 
72 static void
dump_enum(struct dump_ctx * ctx,uint e,const char ** enums,uint enum_count)73 dump_enum(
74    struct dump_ctx *ctx,
75    uint e,
76    const char **enums,
77    uint enum_count )
78 {
79    if (e >= enum_count)
80       ctx->dump_printf( ctx, "%u", e );
81    else
82       ctx->dump_printf( ctx, "%s", enums[e] );
83 }
84 
85 #define EOL()           ctx->dump_printf( ctx, "\n" )
86 #define TXT(S)          ctx->dump_printf( ctx, "%s", S )
87 #define CHR(C)          ctx->dump_printf( ctx, "%c", C )
88 #define UIX(I)          ctx->dump_printf( ctx, "0x%x", I )
89 #define UID(I)          ctx->dump_printf( ctx, "%u", I )
90 #define INSTID(I)       ctx->dump_printf( ctx, "% 3u", I )
91 #define SID(I)          ctx->dump_printf( ctx, "%d", I )
92 #define FLT(F)          ctx->dump_printf( ctx, "%10.4f", F )
93 #define DBL(D)          ctx->dump_printf( ctx, "%10.8f", D )
94 #define HFLT(F)         ctx->dump_printf( ctx, "0x%08x", fui((F)) )
95 #define ENM(E,ENUMS)    dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
96 
97 const char *
98 tgsi_swizzle_names[4] =
99 {
100    "x",
101    "y",
102    "z",
103    "w"
104 };
105 
106 static void
_dump_register_src(struct dump_ctx * ctx,const struct tgsi_full_src_register * src)107 _dump_register_src(
108    struct dump_ctx *ctx,
109    const struct tgsi_full_src_register *src )
110 {
111    TXT(tgsi_file_name(src->Register.File));
112    if (src->Register.Dimension) {
113       if (src->Dimension.Indirect) {
114          CHR( '[' );
115          TXT(tgsi_file_name(src->DimIndirect.File));
116          CHR( '[' );
117          SID( src->DimIndirect.Index );
118          TXT( "]." );
119          ENM( src->DimIndirect.Swizzle, tgsi_swizzle_names );
120          if (src->Dimension.Index != 0) {
121             if (src->Dimension.Index > 0)
122                CHR( '+' );
123             SID( src->Dimension.Index );
124          }
125          CHR( ']' );
126          if (src->DimIndirect.ArrayID) {
127             CHR( '(' );
128             SID( src->DimIndirect.ArrayID );
129             CHR( ')' );
130          }
131       } else {
132          CHR('[');
133          SID(src->Dimension.Index);
134          CHR(']');
135       }
136    }
137    if (src->Register.Indirect) {
138       CHR( '[' );
139       TXT(tgsi_file_name(src->Indirect.File));
140       CHR( '[' );
141       SID( src->Indirect.Index );
142       TXT( "]." );
143       ENM( src->Indirect.Swizzle, tgsi_swizzle_names );
144       if (src->Register.Index != 0) {
145          if (src->Register.Index > 0)
146             CHR( '+' );
147          SID( src->Register.Index );
148       }
149       CHR( ']' );
150       if (src->Indirect.ArrayID) {
151          CHR( '(' );
152          SID( src->Indirect.ArrayID );
153          CHR( ')' );
154       }
155    } else {
156       CHR( '[' );
157       SID( src->Register.Index );
158       CHR( ']' );
159    }
160 }
161 
162 
163 static void
_dump_register_dst(struct dump_ctx * ctx,const struct tgsi_full_dst_register * dst)164 _dump_register_dst(
165    struct dump_ctx *ctx,
166    const struct tgsi_full_dst_register *dst )
167 {
168    TXT(tgsi_file_name(dst->Register.File));
169    if (dst->Register.Dimension) {
170       if (dst->Dimension.Indirect) {
171          CHR( '[' );
172          TXT(tgsi_file_name(dst->DimIndirect.File));
173          CHR( '[' );
174          SID( dst->DimIndirect.Index );
175          TXT( "]." );
176          ENM( dst->DimIndirect.Swizzle, tgsi_swizzle_names );
177          if (dst->Dimension.Index != 0) {
178             if (dst->Dimension.Index > 0)
179                CHR( '+' );
180             SID( dst->Dimension.Index );
181          }
182          CHR( ']' );
183          if (dst->DimIndirect.ArrayID) {
184             CHR( '(' );
185             SID( dst->DimIndirect.ArrayID );
186             CHR( ')' );
187          }
188       } else {
189          CHR('[');
190          SID(dst->Dimension.Index);
191          CHR(']');
192       }
193    }
194    if (dst->Register.Indirect) {
195       CHR( '[' );
196       TXT(tgsi_file_name(dst->Indirect.File));
197       CHR( '[' );
198       SID( dst->Indirect.Index );
199       TXT( "]." );
200       ENM( dst->Indirect.Swizzle, tgsi_swizzle_names );
201       if (dst->Register.Index != 0) {
202          if (dst->Register.Index > 0)
203             CHR( '+' );
204          SID( dst->Register.Index );
205       }
206       CHR( ']' );
207       if (dst->Indirect.ArrayID) {
208          CHR( '(' );
209          SID( dst->Indirect.ArrayID );
210          CHR( ')' );
211       }
212    } else {
213       CHR( '[' );
214       SID( dst->Register.Index );
215       CHR( ']' );
216    }
217 }
218 static void
_dump_writemask(struct dump_ctx * ctx,uint writemask)219 _dump_writemask(
220    struct dump_ctx *ctx,
221    uint writemask )
222 {
223    if (writemask != TGSI_WRITEMASK_XYZW) {
224       CHR( '.' );
225       if (writemask & TGSI_WRITEMASK_X)
226          CHR( 'x' );
227       if (writemask & TGSI_WRITEMASK_Y)
228          CHR( 'y' );
229       if (writemask & TGSI_WRITEMASK_Z)
230          CHR( 'z' );
231       if (writemask & TGSI_WRITEMASK_W)
232          CHR( 'w' );
233    }
234 }
235 
236 static void
dump_imm_data(struct tgsi_iterate_context * iter,union tgsi_immediate_data * data,unsigned num_tokens,unsigned data_type)237 dump_imm_data(struct tgsi_iterate_context *iter,
238               union tgsi_immediate_data *data,
239               unsigned num_tokens,
240               unsigned data_type)
241 {
242    struct dump_ctx *ctx = (struct dump_ctx *)iter;
243    unsigned i ;
244 
245    TXT( " {" );
246 
247    assert( num_tokens <= 4 );
248    for (i = 0; i < num_tokens; i++) {
249       switch (data_type) {
250       case TGSI_IMM_FLOAT64: {
251          union di d;
252          d.ui = data[i].Uint | (uint64_t)data[i+1].Uint << 32;
253          DBL( d.d );
254          i++;
255          break;
256       }
257       case TGSI_IMM_FLOAT32:
258          if (ctx->dump_float_as_hex)
259             HFLT( data[i].Float );
260          else
261             FLT( data[i].Float );
262          break;
263       case TGSI_IMM_UINT32:
264          UID(data[i].Uint);
265          break;
266       case TGSI_IMM_INT32:
267          SID(data[i].Int);
268          break;
269       default:
270          assert( 0 );
271       }
272 
273       if (i < num_tokens - 1)
274          TXT( ", " );
275    }
276    TXT( "}" );
277 }
278 
279 static boolean
iter_declaration(struct tgsi_iterate_context * iter,struct tgsi_full_declaration * decl)280 iter_declaration(
281    struct tgsi_iterate_context *iter,
282    struct tgsi_full_declaration *decl )
283 {
284    struct dump_ctx *ctx = (struct dump_ctx *)iter;
285    boolean patch = decl->Semantic.Name == TGSI_SEMANTIC_PATCH ||
286       decl->Semantic.Name == TGSI_SEMANTIC_TESSINNER ||
287       decl->Semantic.Name == TGSI_SEMANTIC_TESSOUTER ||
288       decl->Semantic.Name == TGSI_SEMANTIC_PRIMID;
289 
290    TXT( "DCL " );
291 
292    TXT(tgsi_file_name(decl->Declaration.File));
293 
294    /* all geometry shader inputs and non-patch tessellation shader inputs are
295     * two dimensional
296     */
297    if (decl->Declaration.File == TGSI_FILE_INPUT &&
298        (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY ||
299         (!patch &&
300          (iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL ||
301           iter->processor.Processor == TGSI_PROCESSOR_TESS_EVAL)))) {
302       TXT("[]");
303    }
304 
305    /* all non-patch tess ctrl shader outputs are two dimensional */
306    if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
307        !patch &&
308        iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL) {
309       TXT("[]");
310    }
311 
312    if (decl->Declaration.Dimension) {
313       CHR('[');
314       SID(decl->Dim.Index2D);
315       CHR(']');
316    }
317 
318    CHR('[');
319    SID(decl->Range.First);
320    if (decl->Range.First != decl->Range.Last) {
321       TXT("..");
322       SID(decl->Range.Last);
323    }
324    CHR(']');
325 
326    _dump_writemask(
327       ctx,
328       decl->Declaration.UsageMask );
329 
330    if (decl->Declaration.Array) {
331       TXT( ", ARRAY(" );
332       SID(decl->Array.ArrayID);
333       CHR(')');
334    }
335 
336    if (decl->Declaration.Local)
337       TXT( ", LOCAL" );
338 
339    if (decl->Declaration.Semantic) {
340       TXT( ", " );
341       ENM( decl->Semantic.Name, tgsi_semantic_names );
342       if (decl->Semantic.Index != 0 ||
343           decl->Semantic.Name == TGSI_SEMANTIC_TEXCOORD ||
344           decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) {
345          CHR( '[' );
346          UID( decl->Semantic.Index );
347          CHR( ']' );
348       }
349    }
350 
351    if (decl->Declaration.File == TGSI_FILE_IMAGE) {
352       TXT(", ");
353       ENM(decl->Image.Resource, tgsi_texture_names);
354       TXT(", ");
355       TXT(util_format_name(decl->Image.Format));
356       if (decl->Image.Writable)
357          TXT(", WR");
358       if (decl->Image.Raw)
359          TXT(", RAW");
360    }
361 
362    if (decl->Declaration.File == TGSI_FILE_BUFFER) {
363       if (decl->Declaration.Atomic)
364          TXT(", ATOMIC");
365    }
366 
367    if (decl->Declaration.File == TGSI_FILE_MEMORY) {
368       switch (decl->Declaration.MemType) {
369       /* Note: ,GLOBAL is optional / the default */
370       case TGSI_MEMORY_TYPE_GLOBAL:  TXT(", GLOBAL");  break;
371       case TGSI_MEMORY_TYPE_SHARED:  TXT(", SHARED");  break;
372       case TGSI_MEMORY_TYPE_PRIVATE: TXT(", PRIVATE"); break;
373       case TGSI_MEMORY_TYPE_INPUT:   TXT(", INPUT");   break;
374       }
375    }
376 
377    if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
378       TXT(", ");
379       ENM(decl->SamplerView.Resource, tgsi_texture_names);
380       TXT(", ");
381       if ((decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeY) &&
382           (decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeZ) &&
383           (decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeW)) {
384          ENM(decl->SamplerView.ReturnTypeX, tgsi_return_type_names);
385       } else {
386          ENM(decl->SamplerView.ReturnTypeX, tgsi_return_type_names);
387          TXT(", ");
388          ENM(decl->SamplerView.ReturnTypeY, tgsi_return_type_names);
389          TXT(", ");
390          ENM(decl->SamplerView.ReturnTypeZ, tgsi_return_type_names);
391          TXT(", ");
392          ENM(decl->SamplerView.ReturnTypeW, tgsi_return_type_names);
393       }
394    }
395 
396    if (decl->Declaration.Interpolate) {
397       if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
398           decl->Declaration.File == TGSI_FILE_INPUT)
399       {
400          TXT( ", " );
401          ENM( decl->Interp.Interpolate, tgsi_interpolate_names );
402       }
403 
404       if (decl->Interp.Location != TGSI_INTERPOLATE_LOC_CENTER) {
405          TXT( ", " );
406          ENM( decl->Interp.Location, tgsi_interpolate_locations );
407       }
408 
409       if (decl->Interp.CylindricalWrap) {
410          TXT(", CYLWRAP_");
411          if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_X) {
412             CHR('X');
413          }
414          if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Y) {
415             CHR('Y');
416          }
417          if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Z) {
418             CHR('Z');
419          }
420          if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_W) {
421             CHR('W');
422          }
423       }
424    }
425 
426    if (decl->Declaration.Invariant) {
427       TXT( ", INVARIANT" );
428    }
429 
430    EOL();
431 
432    return TRUE;
433 }
434 
435 void
tgsi_dump_declaration(const struct tgsi_full_declaration * decl)436 tgsi_dump_declaration(
437    const struct tgsi_full_declaration *decl )
438 {
439    struct dump_ctx ctx;
440 
441    ctx.dump_printf = dump_ctx_printf;
442 
443    iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
444 }
445 
446 static boolean
iter_property(struct tgsi_iterate_context * iter,struct tgsi_full_property * prop)447 iter_property(
448    struct tgsi_iterate_context *iter,
449    struct tgsi_full_property *prop )
450 {
451    int i;
452    struct dump_ctx *ctx = (struct dump_ctx *)iter;
453 
454    TXT( "PROPERTY " );
455    ENM(prop->Property.PropertyName, tgsi_property_names);
456 
457    if (prop->Property.NrTokens > 1)
458       TXT(" ");
459 
460    for (i = 0; i < prop->Property.NrTokens - 1; ++i) {
461       switch (prop->Property.PropertyName) {
462       case TGSI_PROPERTY_GS_INPUT_PRIM:
463       case TGSI_PROPERTY_GS_OUTPUT_PRIM:
464          ENM(prop->u[i].Data, tgsi_primitive_names);
465          break;
466       case TGSI_PROPERTY_FS_COORD_ORIGIN:
467          ENM(prop->u[i].Data, tgsi_fs_coord_origin_names);
468          break;
469       case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
470          ENM(prop->u[i].Data, tgsi_fs_coord_pixel_center_names);
471          break;
472       default:
473          SID( prop->u[i].Data );
474          break;
475       }
476       if (i < prop->Property.NrTokens - 2)
477          TXT( ", " );
478    }
479    EOL();
480 
481    return TRUE;
482 }
483 
tgsi_dump_property(const struct tgsi_full_property * prop)484 void tgsi_dump_property(
485    const struct tgsi_full_property *prop )
486 {
487    struct dump_ctx ctx;
488 
489    ctx.dump_printf = dump_ctx_printf;
490 
491    iter_property( &ctx.iter, (struct tgsi_full_property *)prop );
492 }
493 
494 static boolean
iter_immediate(struct tgsi_iterate_context * iter,struct tgsi_full_immediate * imm)495 iter_immediate(
496    struct tgsi_iterate_context *iter,
497    struct tgsi_full_immediate *imm )
498 {
499    struct dump_ctx *ctx = (struct dump_ctx *) iter;
500 
501    TXT( "IMM[" );
502    SID( ctx->immno++ );
503    TXT( "] " );
504    ENM( imm->Immediate.DataType, tgsi_immediate_type_names );
505 
506    dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1,
507                  imm->Immediate.DataType);
508 
509    EOL();
510 
511    return TRUE;
512 }
513 
514 void
tgsi_dump_immediate(const struct tgsi_full_immediate * imm)515 tgsi_dump_immediate(
516    const struct tgsi_full_immediate *imm )
517 {
518    struct dump_ctx ctx;
519 
520    ctx.dump_printf = dump_ctx_printf;
521 
522    iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
523 }
524 
525 static boolean
iter_instruction(struct tgsi_iterate_context * iter,struct tgsi_full_instruction * inst)526 iter_instruction(
527    struct tgsi_iterate_context *iter,
528    struct tgsi_full_instruction *inst )
529 {
530    struct dump_ctx *ctx = (struct dump_ctx *) iter;
531    uint instno = ctx->instno++;
532    const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
533    uint i;
534    boolean first_reg = TRUE;
535 
536    INSTID( instno );
537    TXT( ": " );
538 
539    ctx->indent -= info->pre_dedent;
540    for(i = 0; (int)i < ctx->indent; ++i)
541       TXT( "  " );
542    ctx->indent += info->post_indent;
543 
544    TXT( info->mnemonic );
545 
546    if (inst->Instruction.Saturate) {
547       TXT( "_SAT" );
548    }
549 
550    for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
551       const struct tgsi_full_dst_register *dst = &inst->Dst[i];
552 
553       if (!first_reg)
554          CHR( ',' );
555       CHR( ' ' );
556 
557       _dump_register_dst( ctx, dst );
558       _dump_writemask( ctx, dst->Register.WriteMask );
559 
560       first_reg = FALSE;
561    }
562 
563    for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
564       const struct tgsi_full_src_register *src = &inst->Src[i];
565 
566       if (!first_reg)
567          CHR( ',' );
568       CHR( ' ' );
569 
570       if (src->Register.Negate)
571          CHR( '-' );
572       if (src->Register.Absolute)
573          CHR( '|' );
574 
575       _dump_register_src(ctx, src);
576 
577       if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
578           src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
579           src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
580           src->Register.SwizzleW != TGSI_SWIZZLE_W) {
581          CHR( '.' );
582          ENM( src->Register.SwizzleX, tgsi_swizzle_names );
583          ENM( src->Register.SwizzleY, tgsi_swizzle_names );
584          ENM( src->Register.SwizzleZ, tgsi_swizzle_names );
585          ENM( src->Register.SwizzleW, tgsi_swizzle_names );
586       }
587 
588       if (src->Register.Absolute)
589          CHR( '|' );
590 
591       first_reg = FALSE;
592    }
593 
594    if (inst->Instruction.Texture) {
595       if (!(inst->Instruction.Opcode >= TGSI_OPCODE_SAMPLE &&
596             inst->Instruction.Opcode <= TGSI_OPCODE_GATHER4)) {
597          TXT( ", " );
598          ENM( inst->Texture.Texture, tgsi_texture_names );
599       }
600       for (i = 0; i < inst->Texture.NumOffsets; i++) {
601          TXT( ", " );
602          TXT(tgsi_file_name(inst->TexOffsets[i].File));
603          CHR( '[' );
604          SID( inst->TexOffsets[i].Index );
605          CHR( ']' );
606          CHR( '.' );
607          ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names);
608          ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names);
609          ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names);
610       }
611    }
612 
613    if (inst->Instruction.Memory) {
614       uint32_t qualifier = inst->Memory.Qualifier;
615       while (qualifier) {
616          int bit = ffs(qualifier) - 1;
617          qualifier &= ~(1U << bit);
618          TXT(", ");
619          ENM(bit, tgsi_memory_names);
620       }
621       if (inst->Memory.Texture) {
622          TXT( ", " );
623          ENM( inst->Memory.Texture, tgsi_texture_names );
624       }
625       if (inst->Memory.Format) {
626          TXT( ", " );
627          TXT( util_format_name(inst->Memory.Format) );
628       }
629    }
630 
631    if (inst->Instruction.Label) {
632       switch (inst->Instruction.Opcode) {
633       case TGSI_OPCODE_IF:
634       case TGSI_OPCODE_UIF:
635       case TGSI_OPCODE_ELSE:
636       case TGSI_OPCODE_BGNLOOP:
637       case TGSI_OPCODE_ENDLOOP:
638       case TGSI_OPCODE_CAL:
639       case TGSI_OPCODE_BGNSUB:
640          TXT( " :" );
641          UID( inst->Label.Label );
642          break;
643       }
644    }
645 
646    /* update indentation */
647    if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
648        inst->Instruction.Opcode == TGSI_OPCODE_UIF ||
649        inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
650        inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
651       ctx->indentation += indent_spaces;
652    }
653 
654    EOL();
655 
656    return TRUE;
657 }
658 
659 void
tgsi_dump_instruction(const struct tgsi_full_instruction * inst,uint instno)660 tgsi_dump_instruction(
661    const struct tgsi_full_instruction *inst,
662    uint instno )
663 {
664    struct dump_ctx ctx;
665 
666    ctx.instno = instno;
667    ctx.immno = instno;
668    ctx.indent = 0;
669    ctx.dump_printf = dump_ctx_printf;
670    ctx.indentation = 0;
671    ctx.file = NULL;
672 
673    iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
674 }
675 
676 static boolean
prolog(struct tgsi_iterate_context * iter)677 prolog(
678    struct tgsi_iterate_context *iter )
679 {
680    struct dump_ctx *ctx = (struct dump_ctx *) iter;
681    ENM( iter->processor.Processor, tgsi_processor_type_names );
682    EOL();
683    return TRUE;
684 }
685 
686 void
tgsi_dump_to_file(const struct tgsi_token * tokens,uint flags,FILE * file)687 tgsi_dump_to_file(const struct tgsi_token *tokens, uint flags, FILE *file)
688 {
689    struct dump_ctx ctx;
690 
691    ctx.iter.prolog = prolog;
692    ctx.iter.iterate_instruction = iter_instruction;
693    ctx.iter.iterate_declaration = iter_declaration;
694    ctx.iter.iterate_immediate = iter_immediate;
695    ctx.iter.iterate_property = iter_property;
696    ctx.iter.epilog = NULL;
697 
698    ctx.instno = 0;
699    ctx.immno = 0;
700    ctx.indent = 0;
701    ctx.dump_printf = dump_ctx_printf;
702    ctx.indentation = 0;
703    ctx.file = file;
704 
705    if (flags & TGSI_DUMP_FLOAT_AS_HEX)
706       ctx.dump_float_as_hex = TRUE;
707    else
708       ctx.dump_float_as_hex = FALSE;
709 
710    tgsi_iterate_shader( tokens, &ctx.iter );
711 }
712 
713 void
tgsi_dump(const struct tgsi_token * tokens,uint flags)714 tgsi_dump(const struct tgsi_token *tokens, uint flags)
715 {
716    tgsi_dump_to_file(tokens, flags, NULL);
717 }
718 
719 struct str_dump_ctx
720 {
721    struct dump_ctx base;
722    char *str;
723    char *ptr;
724    int left;
725    bool nospace;
726 };
727 
728 static void
str_dump_ctx_printf(struct dump_ctx * ctx,const char * format,...)729 str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
730 {
731    struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
732 
733    if(sctx->left > 1) {
734       int written;
735       va_list ap;
736       va_start(ap, format);
737       written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
738       va_end(ap);
739 
740       /* Some complicated logic needed to handle the return value of
741        * vsnprintf:
742        */
743       if (written > 0) {
744          written = MIN2(sctx->left, written);
745          sctx->ptr += written;
746          sctx->left -= written;
747       }
748    } else
749       sctx->nospace = true;
750 }
751 
752 bool
tgsi_dump_str(const struct tgsi_token * tokens,uint flags,char * str,size_t size)753 tgsi_dump_str(
754    const struct tgsi_token *tokens,
755    uint flags,
756    char *str,
757    size_t size)
758 {
759    struct str_dump_ctx ctx;
760 
761    ctx.base.iter.prolog = prolog;
762    ctx.base.iter.iterate_instruction = iter_instruction;
763    ctx.base.iter.iterate_declaration = iter_declaration;
764    ctx.base.iter.iterate_immediate = iter_immediate;
765    ctx.base.iter.iterate_property = iter_property;
766    ctx.base.iter.epilog = NULL;
767 
768    ctx.base.instno = 0;
769    ctx.base.immno = 0;
770    ctx.base.indent = 0;
771    ctx.base.dump_printf = &str_dump_ctx_printf;
772    ctx.base.indentation = 0;
773    ctx.base.file = NULL;
774 
775    ctx.str = str;
776    ctx.str[0] = 0;
777    ctx.ptr = str;
778    ctx.left = (int)size;
779    ctx.nospace = false;
780 
781    if (flags & TGSI_DUMP_FLOAT_AS_HEX)
782       ctx.base.dump_float_as_hex = TRUE;
783    else
784       ctx.base.dump_float_as_hex = FALSE;
785 
786    tgsi_iterate_shader( tokens, &ctx.base.iter );
787 
788    return !ctx.nospace;
789 }
790 
791 void
tgsi_dump_instruction_str(const struct tgsi_full_instruction * inst,uint instno,char * str,size_t size)792 tgsi_dump_instruction_str(
793    const struct tgsi_full_instruction *inst,
794    uint instno,
795    char *str,
796    size_t size)
797 {
798    struct str_dump_ctx ctx;
799 
800    ctx.base.instno = instno;
801    ctx.base.immno = instno;
802    ctx.base.indent = 0;
803    ctx.base.dump_printf = &str_dump_ctx_printf;
804    ctx.base.indentation = 0;
805    ctx.base.file = NULL;
806 
807    ctx.str = str;
808    ctx.str[0] = 0;
809    ctx.ptr = str;
810    ctx.left = (int)size;
811    ctx.nospace = false;
812 
813    iter_instruction( &ctx.base.iter, (struct tgsi_full_instruction *)inst );
814 }
815