1 /**************************************************************************
2  *
3  * Copyright 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_memory.h"
30 #include "util/u_prim.h"
31 #include "pipe/p_defines.h"
32 #include "util/u_inlines.h"
33 #include "tgsi_text.h"
34 #include "tgsi_build.h"
35 #include "tgsi_info.h"
36 #include "tgsi_parse.h"
37 #include "tgsi_sanity.h"
38 #include "tgsi_strings.h"
39 #include "tgsi_util.h"
40 #include "tgsi_dump.h"
41 
is_alpha_underscore(const char * cur)42 static boolean is_alpha_underscore( const char *cur )
43 {
44    return
45       (*cur >= 'a' && *cur <= 'z') ||
46       (*cur >= 'A' && *cur <= 'Z') ||
47       *cur == '_';
48 }
49 
is_digit(const char * cur)50 static boolean is_digit( const char *cur )
51 {
52    return *cur >= '0' && *cur <= '9';
53 }
54 
is_digit_alpha_underscore(const char * cur)55 static boolean is_digit_alpha_underscore( const char *cur )
56 {
57    return is_digit( cur ) || is_alpha_underscore( cur );
58 }
59 
uprcase(char c)60 static char uprcase( char c )
61 {
62    if (c >= 'a' && c <= 'z')
63       return c + 'A' - 'a';
64    return c;
65 }
66 
67 /*
68  * Ignore case of str1 and assume str1 is already uppercase.
69  * Return TRUE iff str1 and str2 are equal.
70  */
71 static int
streq_nocase_uprcase(const char * str1,const char * str2)72 streq_nocase_uprcase(const char *str1,
73                      const char *str2)
74 {
75    while (*str1 && *str2) {
76       if (*str1 != uprcase(*str2))
77          return FALSE;
78       str1++;
79       str2++;
80    }
81    return *str1 == 0 && *str2 == 0;
82 }
83 
84 /* Return TRUE if both strings match.
85  * The second string is terminated by zero.
86  * The pointer to the first string is moved at end of the read word
87  * on success.
88  */
str_match_no_case(const char ** pcur,const char * str)89 static boolean str_match_no_case( const char **pcur, const char *str )
90 {
91    const char *cur = *pcur;
92 
93    while (*str != '\0' && *str == uprcase( *cur )) {
94       str++;
95       cur++;
96    }
97    if (*str == '\0') {
98       *pcur = cur;
99       return TRUE;
100    }
101    return FALSE;
102 }
103 
104 /* Return TRUE if both strings match.
105  * The first string is be terminated by a non-digit non-letter non-underscore
106  * character, the second string is terminated by zero.
107  * The pointer to the first string is moved at end of the read word
108  * on success.
109  */
str_match_nocase_whole(const char ** pcur,const char * str)110 static boolean str_match_nocase_whole( const char **pcur, const char *str )
111 {
112    const char *cur = *pcur;
113 
114    if (str_match_no_case(&cur, str) &&
115        !is_digit_alpha_underscore(cur)) {
116       *pcur = cur;
117       return TRUE;
118    }
119    return FALSE;
120 }
121 
122 /* Eat zero or more whitespaces.
123  */
eat_opt_white(const char ** pcur)124 static void eat_opt_white( const char **pcur )
125 {
126    while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
127       (*pcur)++;
128 }
129 
130 /* Eat one or more whitespaces.
131  * Return TRUE if at least one whitespace eaten.
132  */
eat_white(const char ** pcur)133 static boolean eat_white( const char **pcur )
134 {
135    const char *cur = *pcur;
136 
137    eat_opt_white( pcur );
138    return *pcur > cur;
139 }
140 
141 /* Parse unsigned integer.
142  * No checks for overflow.
143  */
parse_uint(const char ** pcur,uint * val)144 static boolean parse_uint( const char **pcur, uint *val )
145 {
146    const char *cur = *pcur;
147 
148    if (is_digit( cur )) {
149       *val = *cur++ - '0';
150       while (is_digit( cur ))
151          *val = *val * 10 + *cur++ - '0';
152       *pcur = cur;
153       return TRUE;
154    }
155    return FALSE;
156 }
157 
parse_int(const char ** pcur,int * val)158 static boolean parse_int( const char **pcur, int *val )
159 {
160    const char *cur = *pcur;
161    int sign = (*cur == '-' ? -1 : 1);
162 
163    if (*cur == '+' || *cur == '-')
164       cur++;
165 
166    if (parse_uint(&cur, (uint *)val)) {
167       *val *= sign;
168       *pcur = cur;
169       return TRUE;
170    }
171 
172    return FALSE;
173 }
174 
parse_identifier(const char ** pcur,char * ret)175 static boolean parse_identifier( const char **pcur, char *ret )
176 {
177    const char *cur = *pcur;
178    int i = 0;
179    if (is_alpha_underscore( cur )) {
180       ret[i++] = *cur++;
181       while (is_alpha_underscore( cur ) || is_digit( cur ))
182          ret[i++] = *cur++;
183       ret[i++] = '\0';
184       *pcur = cur;
185       return TRUE;
186    }
187    return FALSE;
188 }
189 
190 /* Parse floating point.
191  */
parse_float(const char ** pcur,float * val)192 static boolean parse_float( const char **pcur, float *val )
193 {
194    const char *cur = *pcur;
195    boolean integral_part = FALSE;
196    boolean fractional_part = FALSE;
197 
198    *val = (float) atof( cur );
199 
200    if (*cur == '-' || *cur == '+')
201       cur++;
202    if (is_digit( cur )) {
203       cur++;
204       integral_part = TRUE;
205       while (is_digit( cur ))
206          cur++;
207    }
208    if (*cur == '.') {
209       cur++;
210       if (is_digit( cur )) {
211          cur++;
212          fractional_part = TRUE;
213          while (is_digit( cur ))
214             cur++;
215       }
216    }
217    if (!integral_part && !fractional_part)
218       return FALSE;
219    if (uprcase( *cur ) == 'E') {
220       cur++;
221       if (*cur == '-' || *cur == '+')
222          cur++;
223       if (is_digit( cur )) {
224          cur++;
225          while (is_digit( cur ))
226             cur++;
227       }
228       else
229          return FALSE;
230    }
231    *pcur = cur;
232    return TRUE;
233 }
234 
235 struct translate_ctx
236 {
237    const char *text;
238    const char *cur;
239    struct tgsi_token *tokens;
240    struct tgsi_token *tokens_cur;
241    struct tgsi_token *tokens_end;
242    struct tgsi_header *header;
243    unsigned processor : 4;
244    int implied_array_size : 5;
245 };
246 
report_error(struct translate_ctx * ctx,const char * msg)247 static void report_error( struct translate_ctx *ctx, const char *msg )
248 {
249    int line = 1;
250    int column = 1;
251    const char *itr = ctx->text;
252 
253    while (itr != ctx->cur) {
254       if (*itr == '\n') {
255          column = 1;
256          ++line;
257       }
258       ++column;
259       ++itr;
260    }
261 
262    debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
263 }
264 
265 /* Parse shader header.
266  * Return TRUE for one of the following headers.
267  *    FRAG
268  *    GEOM
269  *    VERT
270  */
parse_header(struct translate_ctx * ctx)271 static boolean parse_header( struct translate_ctx *ctx )
272 {
273    uint processor;
274 
275    if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
276       processor = TGSI_PROCESSOR_FRAGMENT;
277    else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
278       processor = TGSI_PROCESSOR_VERTEX;
279    else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
280       processor = TGSI_PROCESSOR_GEOMETRY;
281    else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
282       processor = TGSI_PROCESSOR_COMPUTE;
283    else {
284       report_error( ctx, "Unknown header" );
285       return FALSE;
286    }
287 
288    if (ctx->tokens_cur >= ctx->tokens_end)
289       return FALSE;
290    ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
291    *ctx->header = tgsi_build_header();
292 
293    if (ctx->tokens_cur >= ctx->tokens_end)
294       return FALSE;
295    *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
296    ctx->processor = processor;
297 
298    return TRUE;
299 }
300 
parse_label(struct translate_ctx * ctx,uint * val)301 static boolean parse_label( struct translate_ctx *ctx, uint *val )
302 {
303    const char *cur = ctx->cur;
304 
305    if (parse_uint( &cur, val )) {
306       eat_opt_white( &cur );
307       if (*cur == ':') {
308          cur++;
309          ctx->cur = cur;
310          return TRUE;
311       }
312    }
313    return FALSE;
314 }
315 
316 static boolean
parse_file(const char ** pcur,uint * file)317 parse_file( const char **pcur, uint *file )
318 {
319    uint i;
320 
321    for (i = 0; i < TGSI_FILE_COUNT; i++) {
322       const char *cur = *pcur;
323 
324       if (str_match_nocase_whole( &cur, tgsi_file_names[i] )) {
325          *pcur = cur;
326          *file = i;
327          return TRUE;
328       }
329    }
330    return FALSE;
331 }
332 
333 static boolean
parse_opt_writemask(struct translate_ctx * ctx,uint * writemask)334 parse_opt_writemask(
335    struct translate_ctx *ctx,
336    uint *writemask )
337 {
338    const char *cur;
339 
340    cur = ctx->cur;
341    eat_opt_white( &cur );
342    if (*cur == '.') {
343       cur++;
344       *writemask = TGSI_WRITEMASK_NONE;
345       eat_opt_white( &cur );
346       if (uprcase( *cur ) == 'X') {
347          cur++;
348          *writemask |= TGSI_WRITEMASK_X;
349       }
350       if (uprcase( *cur ) == 'Y') {
351          cur++;
352          *writemask |= TGSI_WRITEMASK_Y;
353       }
354       if (uprcase( *cur ) == 'Z') {
355          cur++;
356          *writemask |= TGSI_WRITEMASK_Z;
357       }
358       if (uprcase( *cur ) == 'W') {
359          cur++;
360          *writemask |= TGSI_WRITEMASK_W;
361       }
362 
363       if (*writemask == TGSI_WRITEMASK_NONE) {
364          report_error( ctx, "Writemask expected" );
365          return FALSE;
366       }
367 
368       ctx->cur = cur;
369    }
370    else {
371       *writemask = TGSI_WRITEMASK_XYZW;
372    }
373    return TRUE;
374 }
375 
376 
377 /* <register_file_bracket> ::= <file> `['
378  */
379 static boolean
parse_register_file_bracket(struct translate_ctx * ctx,uint * file)380 parse_register_file_bracket(
381    struct translate_ctx *ctx,
382    uint *file )
383 {
384    if (!parse_file( &ctx->cur, file )) {
385       report_error( ctx, "Unknown register file" );
386       return FALSE;
387    }
388    eat_opt_white( &ctx->cur );
389    if (*ctx->cur != '[') {
390       report_error( ctx, "Expected `['" );
391       return FALSE;
392    }
393    ctx->cur++;
394    return TRUE;
395 }
396 
397 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
398  */
399 static boolean
parse_register_file_bracket_index(struct translate_ctx * ctx,uint * file,int * index)400 parse_register_file_bracket_index(
401    struct translate_ctx *ctx,
402    uint *file,
403    int *index )
404 {
405    uint uindex;
406 
407    if (!parse_register_file_bracket( ctx, file ))
408       return FALSE;
409    eat_opt_white( &ctx->cur );
410    if (!parse_uint( &ctx->cur, &uindex )) {
411       report_error( ctx, "Expected literal unsigned integer" );
412       return FALSE;
413    }
414    *index = (int) uindex;
415    return TRUE;
416 }
417 
418 /* Parse simple 1d register operand.
419  *    <register_dst> ::= <register_file_bracket_index> `]'
420  */
421 static boolean
parse_register_1d(struct translate_ctx * ctx,uint * file,int * index)422 parse_register_1d(struct translate_ctx *ctx,
423                   uint *file,
424                   int *index )
425 {
426    if (!parse_register_file_bracket_index( ctx, file, index ))
427       return FALSE;
428    eat_opt_white( &ctx->cur );
429    if (*ctx->cur != ']') {
430       report_error( ctx, "Expected `]'" );
431       return FALSE;
432    }
433    ctx->cur++;
434    return TRUE;
435 }
436 
437 struct parsed_bracket {
438    int index;
439 
440    uint ind_file;
441    int ind_index;
442    uint ind_comp;
443 };
444 
445 
446 static boolean
parse_register_bracket(struct translate_ctx * ctx,struct parsed_bracket * brackets)447 parse_register_bracket(
448    struct translate_ctx *ctx,
449    struct parsed_bracket *brackets)
450 {
451    const char *cur;
452    uint uindex;
453 
454    memset(brackets, 0, sizeof(struct parsed_bracket));
455 
456    eat_opt_white( &ctx->cur );
457 
458    cur = ctx->cur;
459    if (parse_file( &cur, &brackets->ind_file )) {
460       if (!parse_register_1d( ctx, &brackets->ind_file,
461                               &brackets->ind_index ))
462          return FALSE;
463       eat_opt_white( &ctx->cur );
464 
465       if (*ctx->cur == '.') {
466          ctx->cur++;
467          eat_opt_white(&ctx->cur);
468 
469          switch (uprcase(*ctx->cur)) {
470          case 'X':
471             brackets->ind_comp = TGSI_SWIZZLE_X;
472             break;
473          case 'Y':
474             brackets->ind_comp = TGSI_SWIZZLE_Y;
475             break;
476          case 'Z':
477             brackets->ind_comp = TGSI_SWIZZLE_Z;
478             break;
479          case 'W':
480             brackets->ind_comp = TGSI_SWIZZLE_W;
481             break;
482          default:
483             report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
484             return FALSE;
485          }
486          ctx->cur++;
487          eat_opt_white(&ctx->cur);
488       }
489 
490       if (*ctx->cur == '+' || *ctx->cur == '-')
491          parse_int( &ctx->cur, &brackets->index );
492       else
493          brackets->index = 0;
494    }
495    else {
496       if (!parse_uint( &ctx->cur, &uindex )) {
497          report_error( ctx, "Expected literal unsigned integer" );
498          return FALSE;
499       }
500       brackets->index = (int) uindex;
501       brackets->ind_file = TGSI_FILE_NULL;
502       brackets->ind_index = 0;
503    }
504    eat_opt_white( &ctx->cur );
505    if (*ctx->cur != ']') {
506       report_error( ctx, "Expected `]'" );
507       return FALSE;
508    }
509    ctx->cur++;
510    return TRUE;
511 }
512 
513 static boolean
parse_opt_register_src_bracket(struct translate_ctx * ctx,struct parsed_bracket * brackets,int * parsed_brackets)514 parse_opt_register_src_bracket(
515    struct translate_ctx *ctx,
516    struct parsed_bracket *brackets,
517    int *parsed_brackets)
518 {
519    const char *cur = ctx->cur;
520 
521    *parsed_brackets = 0;
522 
523    eat_opt_white( &cur );
524    if (cur[0] == '[') {
525       ++cur;
526       ctx->cur = cur;
527 
528       if (!parse_register_bracket(ctx, brackets))
529          return FALSE;
530 
531       *parsed_brackets = 1;
532    }
533 
534    return TRUE;
535 }
536 
537 
538 /* Parse source register operand.
539  *    <register_src> ::= <register_file_bracket_index> `]' |
540  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
541  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
542  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
543  */
544 static boolean
parse_register_src(struct translate_ctx * ctx,uint * file,struct parsed_bracket * brackets)545 parse_register_src(
546    struct translate_ctx *ctx,
547    uint *file,
548    struct parsed_bracket *brackets)
549 {
550    brackets->ind_comp = TGSI_SWIZZLE_X;
551    if (!parse_register_file_bracket( ctx, file ))
552       return FALSE;
553    if (!parse_register_bracket( ctx, brackets ))
554        return FALSE;
555 
556    return TRUE;
557 }
558 
559 struct parsed_dcl_bracket {
560    uint first;
561    uint last;
562 };
563 
564 static boolean
parse_register_dcl_bracket(struct translate_ctx * ctx,struct parsed_dcl_bracket * bracket)565 parse_register_dcl_bracket(
566    struct translate_ctx *ctx,
567    struct parsed_dcl_bracket *bracket)
568 {
569    uint uindex;
570    memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
571 
572    eat_opt_white( &ctx->cur );
573 
574    if (!parse_uint( &ctx->cur, &uindex )) {
575       /* it can be an empty bracket [] which means its range
576        * is from 0 to some implied size */
577       if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
578          bracket->first = 0;
579          bracket->last = ctx->implied_array_size - 1;
580          goto cleanup;
581       }
582       report_error( ctx, "Expected literal unsigned integer" );
583       return FALSE;
584    }
585    bracket->first = uindex;
586 
587    eat_opt_white( &ctx->cur );
588 
589    if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
590       uint uindex;
591 
592       ctx->cur += 2;
593       eat_opt_white( &ctx->cur );
594       if (!parse_uint( &ctx->cur, &uindex )) {
595          report_error( ctx, "Expected literal integer" );
596          return FALSE;
597       }
598       bracket->last = (int) uindex;
599       eat_opt_white( &ctx->cur );
600    }
601    else {
602       bracket->last = bracket->first;
603    }
604 
605 cleanup:
606    if (*ctx->cur != ']') {
607       report_error( ctx, "Expected `]' or `..'" );
608       return FALSE;
609    }
610    ctx->cur++;
611    return TRUE;
612 }
613 
614 /* Parse register declaration.
615  *    <register_dcl> ::= <register_file_bracket_index> `]' |
616  *                       <register_file_bracket_index> `..' <index> `]'
617  */
618 static boolean
parse_register_dcl(struct translate_ctx * ctx,uint * file,struct parsed_dcl_bracket * brackets,int * num_brackets)619 parse_register_dcl(
620    struct translate_ctx *ctx,
621    uint *file,
622    struct parsed_dcl_bracket *brackets,
623    int *num_brackets)
624 {
625    const char *cur;
626 
627    *num_brackets = 0;
628 
629    if (!parse_register_file_bracket( ctx, file ))
630       return FALSE;
631    if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
632       return FALSE;
633 
634    *num_brackets = 1;
635 
636    cur = ctx->cur;
637    eat_opt_white( &cur );
638 
639    if (cur[0] == '[') {
640       ++cur;
641       ctx->cur = cur;
642       if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
643          return FALSE;
644       /* for geometry shader we don't really care about
645        * the first brackets it's always the size of the
646        * input primitive. so we want to declare just
647        * the index relevant to the semantics which is in
648        * the second bracket */
649       if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
650          brackets[0] = brackets[1];
651          *num_brackets = 1;
652       } else {
653          *num_brackets = 2;
654       }
655    }
656 
657    return TRUE;
658 }
659 
660 
661 /* Parse destination register operand.*/
662 static boolean
parse_register_dst(struct translate_ctx * ctx,uint * file,struct parsed_bracket * brackets)663 parse_register_dst(
664    struct translate_ctx *ctx,
665    uint *file,
666    struct parsed_bracket *brackets)
667 {
668    brackets->ind_comp = TGSI_SWIZZLE_X;
669    if (!parse_register_file_bracket( ctx, file ))
670       return FALSE;
671    if (!parse_register_bracket( ctx, brackets ))
672        return FALSE;
673 
674    return TRUE;
675 }
676 
677 static boolean
parse_dst_operand(struct translate_ctx * ctx,struct tgsi_full_dst_register * dst)678 parse_dst_operand(
679    struct translate_ctx *ctx,
680    struct tgsi_full_dst_register *dst )
681 {
682    uint file;
683    uint writemask;
684    const char *cur;
685    struct parsed_bracket bracket[2];
686    int parsed_opt_brackets;
687 
688    if (!parse_register_dst( ctx, &file, &bracket[0] ))
689       return FALSE;
690    if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
691       return FALSE;
692 
693    cur = ctx->cur;
694    eat_opt_white( &cur );
695 
696    if (!parse_opt_writemask( ctx, &writemask ))
697       return FALSE;
698 
699    dst->Register.File = file;
700    if (parsed_opt_brackets) {
701       dst->Register.Dimension = 1;
702       dst->Dimension.Indirect = 0;
703       dst->Dimension.Dimension = 0;
704       dst->Dimension.Index = bracket[0].index;
705       bracket[0] = bracket[1];
706    }
707    dst->Register.Index = bracket[0].index;
708    dst->Register.WriteMask = writemask;
709    if (bracket[0].ind_file != TGSI_FILE_NULL) {
710       dst->Register.Indirect = 1;
711       dst->Indirect.File = bracket[0].ind_file;
712       dst->Indirect.Index = bracket[0].ind_index;
713       dst->Indirect.SwizzleX = bracket[0].ind_comp;
714       dst->Indirect.SwizzleY = bracket[0].ind_comp;
715       dst->Indirect.SwizzleZ = bracket[0].ind_comp;
716       dst->Indirect.SwizzleW = bracket[0].ind_comp;
717    }
718    return TRUE;
719 }
720 
721 static boolean
parse_optional_swizzle(struct translate_ctx * ctx,uint swizzle[4],boolean * parsed_swizzle)722 parse_optional_swizzle(
723    struct translate_ctx *ctx,
724    uint swizzle[4],
725    boolean *parsed_swizzle )
726 {
727    const char *cur = ctx->cur;
728 
729    *parsed_swizzle = FALSE;
730 
731    eat_opt_white( &cur );
732    if (*cur == '.') {
733       uint i;
734 
735       cur++;
736       eat_opt_white( &cur );
737       for (i = 0; i < 4; i++) {
738          if (uprcase( *cur ) == 'X')
739             swizzle[i] = TGSI_SWIZZLE_X;
740          else if (uprcase( *cur ) == 'Y')
741             swizzle[i] = TGSI_SWIZZLE_Y;
742          else if (uprcase( *cur ) == 'Z')
743             swizzle[i] = TGSI_SWIZZLE_Z;
744          else if (uprcase( *cur ) == 'W')
745             swizzle[i] = TGSI_SWIZZLE_W;
746          else {
747 	    report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
748 	    return FALSE;
749          }
750          cur++;
751       }
752       *parsed_swizzle = TRUE;
753       ctx->cur = cur;
754    }
755    return TRUE;
756 }
757 
758 static boolean
parse_src_operand(struct translate_ctx * ctx,struct tgsi_full_src_register * src)759 parse_src_operand(
760    struct translate_ctx *ctx,
761    struct tgsi_full_src_register *src )
762 {
763    uint file;
764    uint swizzle[4];
765    boolean parsed_swizzle;
766    struct parsed_bracket bracket[2];
767    int parsed_opt_brackets;
768 
769    if (*ctx->cur == '-') {
770       ctx->cur++;
771       eat_opt_white( &ctx->cur );
772       src->Register.Negate = 1;
773    }
774 
775    if (*ctx->cur == '|') {
776       ctx->cur++;
777       eat_opt_white( &ctx->cur );
778       src->Register.Absolute = 1;
779    }
780 
781    if (!parse_register_src(ctx, &file, &bracket[0]))
782       return FALSE;
783    if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
784       return FALSE;
785 
786    src->Register.File = file;
787    if (parsed_opt_brackets) {
788       src->Register.Dimension = 1;
789       src->Dimension.Indirect = 0;
790       src->Dimension.Dimension = 0;
791       src->Dimension.Index = bracket[0].index;
792       bracket[0] = bracket[1];
793    }
794    src->Register.Index = bracket[0].index;
795    if (bracket[0].ind_file != TGSI_FILE_NULL) {
796       src->Register.Indirect = 1;
797       src->Indirect.File = bracket[0].ind_file;
798       src->Indirect.Index = bracket[0].ind_index;
799       src->Indirect.SwizzleX = bracket[0].ind_comp;
800       src->Indirect.SwizzleY = bracket[0].ind_comp;
801       src->Indirect.SwizzleZ = bracket[0].ind_comp;
802       src->Indirect.SwizzleW = bracket[0].ind_comp;
803    }
804 
805    /* Parse optional swizzle.
806     */
807    if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
808       if (parsed_swizzle) {
809          src->Register.SwizzleX = swizzle[0];
810          src->Register.SwizzleY = swizzle[1];
811          src->Register.SwizzleZ = swizzle[2];
812          src->Register.SwizzleW = swizzle[3];
813       }
814    }
815 
816    if (src->Register.Absolute) {
817       eat_opt_white( &ctx->cur );
818       if (*ctx->cur != '|') {
819          report_error( ctx, "Expected `|'" );
820          return FALSE;
821       }
822       ctx->cur++;
823    }
824 
825 
826    return TRUE;
827 }
828 
829 static boolean
match_inst(const char ** pcur,unsigned * saturate,const struct tgsi_opcode_info * info)830 match_inst(const char **pcur,
831            unsigned *saturate,
832            const struct tgsi_opcode_info *info)
833 {
834    const char *cur = *pcur;
835 
836    /* simple case: the whole string matches the instruction name */
837    if (str_match_nocase_whole(&cur, info->mnemonic)) {
838       *pcur = cur;
839       *saturate = TGSI_SAT_NONE;
840       return TRUE;
841    }
842 
843    if (str_match_no_case(&cur, info->mnemonic)) {
844       /* the instruction has a suffix, figure it out */
845       if (str_match_nocase_whole(&cur, "_SAT")) {
846          *pcur = cur;
847          *saturate = TGSI_SAT_ZERO_ONE;
848          return TRUE;
849       }
850 
851       if (str_match_nocase_whole(&cur, "_SATNV")) {
852          *pcur = cur;
853          *saturate = TGSI_SAT_MINUS_PLUS_ONE;
854          return TRUE;
855       }
856    }
857 
858    return FALSE;
859 }
860 
861 static boolean
parse_instruction(struct translate_ctx * ctx,boolean has_label)862 parse_instruction(
863    struct translate_ctx *ctx,
864    boolean has_label )
865 {
866    uint i;
867    uint saturate = TGSI_SAT_NONE;
868    const struct tgsi_opcode_info *info;
869    struct tgsi_full_instruction inst;
870    const char *cur;
871    uint advance;
872 
873    inst = tgsi_default_full_instruction();
874 
875    /* Parse predicate.
876     */
877    eat_opt_white( &ctx->cur );
878    if (*ctx->cur == '(') {
879       uint file;
880       int index;
881       uint swizzle[4];
882       boolean parsed_swizzle;
883 
884       inst.Instruction.Predicate = 1;
885 
886       ctx->cur++;
887       if (*ctx->cur == '!') {
888          ctx->cur++;
889          inst.Predicate.Negate = 1;
890       }
891 
892       if (!parse_register_1d( ctx, &file, &index ))
893          return FALSE;
894 
895       if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
896          if (parsed_swizzle) {
897             inst.Predicate.SwizzleX = swizzle[0];
898             inst.Predicate.SwizzleY = swizzle[1];
899             inst.Predicate.SwizzleZ = swizzle[2];
900             inst.Predicate.SwizzleW = swizzle[3];
901          }
902       }
903 
904       if (*ctx->cur != ')') {
905          report_error( ctx, "Expected `)'" );
906          return FALSE;
907       }
908 
909       ctx->cur++;
910    }
911 
912    /* Parse instruction name.
913     */
914    eat_opt_white( &ctx->cur );
915    for (i = 0; i < TGSI_OPCODE_LAST; i++) {
916       cur = ctx->cur;
917 
918       info = tgsi_get_opcode_info( i );
919       if (match_inst(&cur, &saturate, info)) {
920          if (info->num_dst + info->num_src + info->is_tex == 0) {
921             ctx->cur = cur;
922             break;
923          }
924          else if (*cur == '\0' || eat_white( &cur )) {
925             ctx->cur = cur;
926             break;
927          }
928       }
929    }
930    if (i == TGSI_OPCODE_LAST) {
931       if (has_label)
932          report_error( ctx, "Unknown opcode" );
933       else
934          report_error( ctx, "Expected `DCL', `IMM' or a label" );
935       return FALSE;
936    }
937 
938    inst.Instruction.Opcode = i;
939    inst.Instruction.Saturate = saturate;
940    inst.Instruction.NumDstRegs = info->num_dst;
941    inst.Instruction.NumSrcRegs = info->num_src;
942 
943    /* Parse instruction operands.
944     */
945    for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
946       if (i > 0) {
947          eat_opt_white( &ctx->cur );
948          if (*ctx->cur != ',') {
949             report_error( ctx, "Expected `,'" );
950             return FALSE;
951          }
952          ctx->cur++;
953          eat_opt_white( &ctx->cur );
954       }
955 
956       if (i < info->num_dst) {
957          if (!parse_dst_operand( ctx, &inst.Dst[i] ))
958             return FALSE;
959       }
960       else if (i < info->num_dst + info->num_src) {
961          if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
962             return FALSE;
963       }
964       else {
965          uint j;
966 
967          for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
968             if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
969                inst.Instruction.Texture = 1;
970                inst.Texture.Texture = j;
971                break;
972             }
973          }
974          if (j == TGSI_TEXTURE_COUNT) {
975             report_error( ctx, "Expected texture target" );
976             return FALSE;
977          }
978       }
979    }
980 
981    cur = ctx->cur;
982    eat_opt_white( &cur );
983    if (info->is_branch && *cur == ':') {
984       uint target;
985 
986       cur++;
987       eat_opt_white( &cur );
988       if (!parse_uint( &cur, &target )) {
989          report_error( ctx, "Expected a label" );
990          return FALSE;
991       }
992       inst.Instruction.Label = 1;
993       inst.Label.Label = target;
994       ctx->cur = cur;
995    }
996 
997    advance = tgsi_build_full_instruction(
998       &inst,
999       ctx->tokens_cur,
1000       ctx->header,
1001       (uint) (ctx->tokens_end - ctx->tokens_cur) );
1002    if (advance == 0)
1003       return FALSE;
1004    ctx->tokens_cur += advance;
1005 
1006    return TRUE;
1007 }
1008 
1009 /* parses a 4-touple of the form {x, y, z, w}
1010  * where x, y, z, w are numbers */
parse_immediate_data(struct translate_ctx * ctx,unsigned type,union tgsi_immediate_data * values)1011 static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
1012                                     union tgsi_immediate_data *values)
1013 {
1014    unsigned i;
1015    int ret;
1016 
1017    eat_opt_white( &ctx->cur );
1018    if (*ctx->cur != '{') {
1019       report_error( ctx, "Expected `{'" );
1020       return FALSE;
1021    }
1022    ctx->cur++;
1023    for (i = 0; i < 4; i++) {
1024       eat_opt_white( &ctx->cur );
1025       if (i > 0) {
1026          if (*ctx->cur != ',') {
1027             report_error( ctx, "Expected `,'" );
1028             return FALSE;
1029          }
1030          ctx->cur++;
1031          eat_opt_white( &ctx->cur );
1032       }
1033 
1034       switch (type) {
1035       case TGSI_IMM_FLOAT32:
1036          ret = parse_float(&ctx->cur, &values[i].Float);
1037          break;
1038       case TGSI_IMM_UINT32:
1039          ret = parse_uint(&ctx->cur, &values[i].Uint);
1040          break;
1041       case TGSI_IMM_INT32:
1042          ret = parse_int(&ctx->cur, &values[i].Int);
1043          break;
1044       default:
1045          assert(0);
1046          ret = FALSE;
1047          break;
1048       }
1049 
1050       if (!ret) {
1051          report_error( ctx, "Expected immediate constant" );
1052          return FALSE;
1053       }
1054    }
1055    eat_opt_white( &ctx->cur );
1056    if (*ctx->cur != '}') {
1057       report_error( ctx, "Expected `}'" );
1058       return FALSE;
1059    }
1060    ctx->cur++;
1061 
1062    return TRUE;
1063 }
1064 
parse_declaration(struct translate_ctx * ctx)1065 static boolean parse_declaration( struct translate_ctx *ctx )
1066 {
1067    struct tgsi_full_declaration decl;
1068    uint file;
1069    struct parsed_dcl_bracket brackets[2];
1070    int num_brackets;
1071    uint writemask;
1072    const char *cur, *cur2;
1073    uint advance;
1074    boolean is_vs_input;
1075    boolean is_imm_array;
1076 
1077    if (!eat_white( &ctx->cur )) {
1078       report_error( ctx, "Syntax error" );
1079       return FALSE;
1080    }
1081    if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1082       return FALSE;
1083    if (!parse_opt_writemask( ctx, &writemask ))
1084       return FALSE;
1085 
1086    decl = tgsi_default_full_declaration();
1087    decl.Declaration.File = file;
1088    decl.Declaration.UsageMask = writemask;
1089 
1090    if (num_brackets == 1) {
1091       decl.Range.First = brackets[0].first;
1092       decl.Range.Last = brackets[0].last;
1093    } else {
1094       decl.Range.First = brackets[1].first;
1095       decl.Range.Last = brackets[1].last;
1096 
1097       decl.Declaration.Dimension = 1;
1098       decl.Dim.Index2D = brackets[0].first;
1099    }
1100 
1101    is_vs_input = (file == TGSI_FILE_INPUT &&
1102                   ctx->processor == TGSI_PROCESSOR_VERTEX);
1103    is_imm_array = (file == TGSI_FILE_IMMEDIATE_ARRAY);
1104 
1105    cur = ctx->cur;
1106    eat_opt_white( &cur );
1107    if (*cur == ',' && !is_vs_input) {
1108       uint i, j;
1109 
1110       cur++;
1111       eat_opt_white( &cur );
1112       if (file == TGSI_FILE_RESOURCE) {
1113          for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1114             if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1115                decl.Resource.Resource = i;
1116                break;
1117             }
1118          }
1119          if (i == TGSI_TEXTURE_COUNT) {
1120             report_error(ctx, "Expected texture target");
1121             return FALSE;
1122          }
1123 
1124          cur2 = cur;
1125          eat_opt_white(&cur2);
1126          while (*cur2 == ',') {
1127             cur2++;
1128             eat_opt_white(&cur2);
1129             if (str_match_nocase_whole(&cur2, "RAW")) {
1130                decl.Resource.Raw = 1;
1131 
1132             } else if (str_match_nocase_whole(&cur2, "WR")) {
1133                decl.Resource.Writable = 1;
1134 
1135             } else {
1136                break;
1137             }
1138             cur = cur2;
1139             eat_opt_white(&cur2);
1140          }
1141 
1142          ctx->cur = cur;
1143 
1144       } else if (file == TGSI_FILE_SAMPLER_VIEW) {
1145          for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1146             if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1147                decl.SamplerView.Resource = i;
1148                break;
1149             }
1150          }
1151          if (i == TGSI_TEXTURE_COUNT) {
1152             report_error(ctx, "Expected texture target");
1153             return FALSE;
1154          }
1155          eat_opt_white( &cur );
1156          if (*cur != ',') {
1157             report_error( ctx, "Expected `,'" );
1158             return FALSE;
1159          }
1160          ++cur;
1161          eat_opt_white( &cur );
1162          for (j = 0; j < 4; ++j) {
1163             for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
1164                if (str_match_nocase_whole(&cur, tgsi_type_names[i])) {
1165                   switch (j) {
1166                   case 0:
1167                      decl.SamplerView.ReturnTypeX = i;
1168                      break;
1169                   case 1:
1170                      decl.SamplerView.ReturnTypeY = i;
1171                      break;
1172                   case 2:
1173                      decl.SamplerView.ReturnTypeZ = i;
1174                      break;
1175                   case 3:
1176                      decl.SamplerView.ReturnTypeW = i;
1177                      break;
1178                   default:
1179                      assert(0);
1180                   }
1181                   break;
1182                }
1183             }
1184             if (i == PIPE_TYPE_COUNT) {
1185                if (j == 0 || j >  2) {
1186                   report_error(ctx, "Expected type name");
1187                   return FALSE;
1188                }
1189                break;
1190             } else {
1191                cur2 = cur;
1192                eat_opt_white( &cur2 );
1193                if (*cur2 == ',') {
1194                   cur2++;
1195                   eat_opt_white( &cur2 );
1196                   cur = cur2;
1197                   continue;
1198                } else
1199                   break;
1200             }
1201          }
1202          if (j < 4) {
1203             decl.SamplerView.ReturnTypeY =
1204                decl.SamplerView.ReturnTypeZ =
1205                decl.SamplerView.ReturnTypeW =
1206                decl.SamplerView.ReturnTypeX;
1207          }
1208          ctx->cur = cur;
1209       } else {
1210          if (str_match_nocase_whole(&cur, "LOCAL")) {
1211             decl.Declaration.Local = 1;
1212             ctx->cur = cur;
1213          }
1214 
1215          cur = ctx->cur;
1216          eat_opt_white( &cur );
1217          if (*cur == ',') {
1218             cur++;
1219             eat_opt_white( &cur );
1220 
1221             for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1222                if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
1223                   uint index;
1224 
1225                   cur2 = cur;
1226                   eat_opt_white( &cur2 );
1227                   if (*cur2 == '[') {
1228                      cur2++;
1229                      eat_opt_white( &cur2 );
1230                      if (!parse_uint( &cur2, &index )) {
1231                         report_error( ctx, "Expected literal integer" );
1232                         return FALSE;
1233                      }
1234                      eat_opt_white( &cur2 );
1235                      if (*cur2 != ']') {
1236                         report_error( ctx, "Expected `]'" );
1237                         return FALSE;
1238                      }
1239                      cur2++;
1240 
1241                      decl.Semantic.Index = index;
1242 
1243                      cur = cur2;
1244                   }
1245 
1246                   decl.Declaration.Semantic = 1;
1247                   decl.Semantic.Name = i;
1248 
1249                   ctx->cur = cur;
1250                   break;
1251                }
1252             }
1253          }
1254       }
1255    } else if (is_imm_array) {
1256       unsigned i;
1257       union tgsi_immediate_data *vals_itr;
1258       /* we have our immediate data */
1259       if (*cur != '{') {
1260          report_error( ctx, "Immediate array without data" );
1261          return FALSE;
1262       }
1263       ++cur;
1264       ctx->cur = cur;
1265 
1266       decl.ImmediateData.u =
1267          MALLOC(sizeof(union tgsi_immediate_data) * 4 *
1268                 (decl.Range.Last + 1));
1269       vals_itr = decl.ImmediateData.u;
1270       for (i = 0; i <= decl.Range.Last; ++i) {
1271          if (!parse_immediate_data(ctx, TGSI_IMM_FLOAT32, vals_itr)) {
1272             FREE(decl.ImmediateData.u);
1273             return FALSE;
1274          }
1275          vals_itr += 4;
1276          eat_opt_white( &ctx->cur );
1277          if (*ctx->cur != ',') {
1278             if (i !=  decl.Range.Last) {
1279                report_error( ctx, "Not enough data in immediate array!" );
1280                FREE(decl.ImmediateData.u);
1281                return FALSE;
1282             }
1283          } else
1284             ++ctx->cur;
1285       }
1286       eat_opt_white( &ctx->cur );
1287       if (*ctx->cur != '}') {
1288          FREE(decl.ImmediateData.u);
1289          report_error( ctx, "Immediate array data missing closing '}'" );
1290          return FALSE;
1291       }
1292       ++ctx->cur;
1293    }
1294 
1295    cur = ctx->cur;
1296    eat_opt_white( &cur );
1297    if (*cur == ',' && !is_vs_input) {
1298       uint i;
1299 
1300       cur++;
1301       eat_opt_white( &cur );
1302       for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1303          if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
1304             decl.Declaration.Interpolate = 1;
1305             decl.Interp.Interpolate = i;
1306 
1307             ctx->cur = cur;
1308             break;
1309          }
1310       }
1311       if (i == TGSI_INTERPOLATE_COUNT) {
1312          report_error( ctx, "Expected semantic or interpolate attribute" );
1313          return FALSE;
1314       }
1315    }
1316 
1317    advance = tgsi_build_full_declaration(
1318       &decl,
1319       ctx->tokens_cur,
1320       ctx->header,
1321       (uint) (ctx->tokens_end - ctx->tokens_cur) );
1322 
1323    if (is_imm_array)
1324       FREE(decl.ImmediateData.u);
1325 
1326    if (advance == 0)
1327       return FALSE;
1328    ctx->tokens_cur += advance;
1329 
1330    return TRUE;
1331 }
1332 
parse_immediate(struct translate_ctx * ctx)1333 static boolean parse_immediate( struct translate_ctx *ctx )
1334 {
1335    struct tgsi_full_immediate imm;
1336    uint advance;
1337    int type;
1338 
1339    if (!eat_white( &ctx->cur )) {
1340       report_error( ctx, "Syntax error" );
1341       return FALSE;
1342    }
1343    for (type = 0; type < Elements(tgsi_immediate_type_names); ++type) {
1344       if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
1345          break;
1346    }
1347    if (type == Elements(tgsi_immediate_type_names)) {
1348       report_error( ctx, "Expected immediate type" );
1349       return FALSE;
1350    }
1351 
1352    imm = tgsi_default_full_immediate();
1353    imm.Immediate.NrTokens += 4;
1354    imm.Immediate.DataType = type;
1355    parse_immediate_data(ctx, type, imm.u);
1356 
1357    advance = tgsi_build_full_immediate(
1358       &imm,
1359       ctx->tokens_cur,
1360       ctx->header,
1361       (uint) (ctx->tokens_end - ctx->tokens_cur) );
1362    if (advance == 0)
1363       return FALSE;
1364    ctx->tokens_cur += advance;
1365 
1366    return TRUE;
1367 }
1368 
1369 static boolean
parse_primitive(const char ** pcur,uint * primitive)1370 parse_primitive( const char **pcur, uint *primitive )
1371 {
1372    uint i;
1373 
1374    for (i = 0; i < PIPE_PRIM_MAX; i++) {
1375       const char *cur = *pcur;
1376 
1377       if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
1378          *primitive = i;
1379          *pcur = cur;
1380          return TRUE;
1381       }
1382    }
1383    return FALSE;
1384 }
1385 
1386 static boolean
parse_fs_coord_origin(const char ** pcur,uint * fs_coord_origin)1387 parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1388 {
1389    uint i;
1390 
1391    for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
1392       const char *cur = *pcur;
1393 
1394       if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
1395          *fs_coord_origin = i;
1396          *pcur = cur;
1397          return TRUE;
1398       }
1399    }
1400    return FALSE;
1401 }
1402 
1403 static boolean
parse_fs_coord_pixel_center(const char ** pcur,uint * fs_coord_pixel_center)1404 parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1405 {
1406    uint i;
1407 
1408    for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
1409       const char *cur = *pcur;
1410 
1411       if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
1412          *fs_coord_pixel_center = i;
1413          *pcur = cur;
1414          return TRUE;
1415       }
1416    }
1417    return FALSE;
1418 }
1419 
1420 
parse_property(struct translate_ctx * ctx)1421 static boolean parse_property( struct translate_ctx *ctx )
1422 {
1423    struct tgsi_full_property prop;
1424    uint property_name;
1425    uint values[8];
1426    uint advance;
1427    char id[64];
1428 
1429    if (!eat_white( &ctx->cur )) {
1430       report_error( ctx, "Syntax error" );
1431       return FALSE;
1432    }
1433    if (!parse_identifier( &ctx->cur, id )) {
1434       report_error( ctx, "Syntax error" );
1435       return FALSE;
1436    }
1437    for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1438         ++property_name) {
1439       if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
1440          break;
1441       }
1442    }
1443    if (property_name >= TGSI_PROPERTY_COUNT) {
1444       debug_printf( "\nError: Unknown property : '%s'", id );
1445       return FALSE;
1446    }
1447 
1448    eat_opt_white( &ctx->cur );
1449    switch(property_name) {
1450    case TGSI_PROPERTY_GS_INPUT_PRIM:
1451    case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1452       if (!parse_primitive(&ctx->cur, &values[0] )) {
1453          report_error( ctx, "Unknown primitive name as property!" );
1454          return FALSE;
1455       }
1456       if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1457           ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
1458          ctx->implied_array_size = u_vertices_per_prim(values[0]);
1459       }
1460       break;
1461    case TGSI_PROPERTY_FS_COORD_ORIGIN:
1462       if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1463          report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1464          return FALSE;
1465       }
1466       break;
1467    case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1468       if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1469          report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1470          return FALSE;
1471       }
1472       break;
1473    case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
1474    default:
1475       if (!parse_uint(&ctx->cur, &values[0] )) {
1476          report_error( ctx, "Expected unsigned integer as property!" );
1477          return FALSE;
1478       }
1479    }
1480 
1481    prop = tgsi_default_full_property();
1482    prop.Property.PropertyName = property_name;
1483    prop.Property.NrTokens += 1;
1484    prop.u[0].Data = values[0];
1485 
1486    advance = tgsi_build_full_property(
1487       &prop,
1488       ctx->tokens_cur,
1489       ctx->header,
1490       (uint) (ctx->tokens_end - ctx->tokens_cur) );
1491    if (advance == 0)
1492       return FALSE;
1493    ctx->tokens_cur += advance;
1494 
1495    return TRUE;
1496 }
1497 
1498 
translate(struct translate_ctx * ctx)1499 static boolean translate( struct translate_ctx *ctx )
1500 {
1501    eat_opt_white( &ctx->cur );
1502    if (!parse_header( ctx ))
1503       return FALSE;
1504 
1505    while (*ctx->cur != '\0') {
1506       uint label_val = 0;
1507       if (!eat_white( &ctx->cur )) {
1508          report_error( ctx, "Syntax error" );
1509          return FALSE;
1510       }
1511 
1512       if (*ctx->cur == '\0')
1513          break;
1514       if (parse_label( ctx, &label_val )) {
1515          if (!parse_instruction( ctx, TRUE ))
1516             return FALSE;
1517       }
1518       else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
1519          if (!parse_declaration( ctx ))
1520             return FALSE;
1521       }
1522       else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
1523          if (!parse_immediate( ctx ))
1524             return FALSE;
1525       }
1526       else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
1527          if (!parse_property( ctx ))
1528             return FALSE;
1529       }
1530       else if (!parse_instruction( ctx, FALSE )) {
1531          return FALSE;
1532       }
1533    }
1534 
1535    return TRUE;
1536 }
1537 
1538 boolean
tgsi_text_translate(const char * text,struct tgsi_token * tokens,uint num_tokens)1539 tgsi_text_translate(
1540    const char *text,
1541    struct tgsi_token *tokens,
1542    uint num_tokens )
1543 {
1544    struct translate_ctx ctx;
1545 
1546    ctx.text = text;
1547    ctx.cur = text;
1548    ctx.tokens = tokens;
1549    ctx.tokens_cur = tokens;
1550    ctx.tokens_end = tokens + num_tokens;
1551 
1552    if (!translate( &ctx ))
1553       return FALSE;
1554 
1555    return tgsi_sanity_check( tokens );
1556 }
1557