xref: /aosp_15_r20/external/mesa3d/src/gallium/auxiliary/tgsi/tgsi_text.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /**************************************************************************
2  *
3  * Copyright 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_memory.h"
30 #include "pipe/p_defines.h"
31 #include "util/u_inlines.h"
32 #include "util/strtod.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 bool 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 bool is_digit( const char *cur )
51 {
52    return *cur >= '0' && *cur <= '9';
53 }
54 
is_digit_alpha_underscore(const char * cur)55 static bool 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 bool 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 bool 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 /* Return the array index that matches starting at *pcur, where the string at
123  * *pcur is terminated by a non-digit non-letter non-underscore.
124  * Returns -1 if no match is found.
125  *
126  * On success, the pointer to the first string is moved to the end of the read
127  * word.
128  */
str_match_name_from_array(const char ** pcur,const char * const * array,unsigned array_size)129 static int str_match_name_from_array(const char **pcur,
130                                      const char * const *array,
131                                      unsigned array_size)
132 {
133    for (unsigned j = 0; j < array_size; ++j) {
134       if (str_match_nocase_whole(pcur, array[j]))
135          return j;
136    }
137    return -1;
138 }
139 
140 /* Return the format corresponding to the name at *pcur.
141  * Returns -1 if there is no format name.
142  *
143  * On success, the pointer to the string is moved to the end of the read format
144  * name.
145  */
str_match_format(const char ** pcur)146 static int str_match_format(const char **pcur)
147 {
148    for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) {
149       const struct util_format_description *desc =
150          util_format_description(i);
151       if (str_match_nocase_whole(pcur, desc->name)) {
152          return i;
153       }
154    }
155    return -1;
156 }
157 
158 /* Eat zero or more whitespaces.
159  */
eat_opt_white(const char ** pcur)160 static void eat_opt_white( const char **pcur )
161 {
162    while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
163       (*pcur)++;
164 }
165 
166 /* Eat one or more whitespaces.
167  * Return TRUE if at least one whitespace eaten.
168  */
eat_white(const char ** pcur)169 static bool eat_white( const char **pcur )
170 {
171    const char *cur = *pcur;
172 
173    eat_opt_white( pcur );
174    return *pcur > cur;
175 }
176 
177 /* Parse unsigned integer.
178  * No checks for overflow.
179  */
parse_uint(const char ** pcur,unsigned * val)180 static bool parse_uint( const char **pcur, unsigned *val )
181 {
182    const char *cur = *pcur;
183 
184    if (is_digit( cur )) {
185       *val = *cur++ - '0';
186       while (is_digit( cur ))
187          *val = *val * 10 + *cur++ - '0';
188       *pcur = cur;
189       return true;
190    }
191    return false;
192 }
193 
parse_int(const char ** pcur,int * val)194 static bool parse_int( const char **pcur, int *val )
195 {
196    const char *cur = *pcur;
197    int sign = (*cur == '-' ? -1 : 1);
198 
199    if (*cur == '+' || *cur == '-')
200       cur++;
201 
202    if (parse_uint(&cur, (unsigned *)val)) {
203       *val *= sign;
204       *pcur = cur;
205       return true;
206    }
207 
208    return false;
209 }
210 
parse_identifier(const char ** pcur,char * ret,size_t len)211 static bool parse_identifier( const char **pcur, char *ret, size_t len )
212 {
213    const char *cur = *pcur;
214    size_t i = 0;
215    if (is_alpha_underscore( cur )) {
216       ret[i++] = *cur++;
217       while (is_alpha_underscore( cur ) || is_digit( cur )) {
218          if (i == len - 1)
219             return false;
220          ret[i++] = *cur++;
221       }
222       ret[i++] = '\0';
223       *pcur = cur;
224       return true;
225    }
226    return false;
227 }
228 
229 /* Parse floating point.
230  */
parse_float(const char ** pcur,float * val)231 static bool parse_float( const char **pcur, float *val )
232 {
233    const char *cur = *pcur;
234    *val = _mesa_strtof(cur, (char**)pcur);
235    if (*pcur == cur)
236       return false;
237    return true;
238 }
239 
parse_double(const char ** pcur,uint32_t * val0,uint32_t * val1)240 static bool parse_double( const char **pcur, uint32_t *val0, uint32_t *val1)
241 {
242    const char *cur = *pcur;
243    union {
244       double dval;
245       uint32_t uval[2];
246    } v;
247 
248    v.dval = _mesa_strtod(cur, (char**)pcur);
249    if (*pcur == cur)
250       return false;
251 
252    *val0 = v.uval[0];
253    *val1 = v.uval[1];
254 
255    return true;
256 }
257 
parse_int64(const char ** pcur,uint32_t * val0,uint32_t * val1)258 static bool parse_int64( const char **pcur, uint32_t *val0, uint32_t *val1)
259 {
260    const char *cur = *pcur;
261    union {
262       int64_t i64val;
263       uint32_t uval[2];
264    } v;
265 
266    v.i64val = strtoll(cur, (char**)pcur, 0);
267    if (*pcur == cur)
268       return false;
269 
270    *val0 = v.uval[0];
271    *val1 = v.uval[1];
272 
273    return true;
274 }
275 
parse_uint64(const char ** pcur,uint32_t * val0,uint32_t * val1)276 static bool parse_uint64( const char **pcur, uint32_t *val0, uint32_t *val1)
277 {
278    const char *cur = *pcur;
279    union {
280       uint64_t u64val;
281       uint32_t uval[2];
282    } v;
283 
284    v.u64val = strtoull(cur, (char**)pcur, 0);
285    if (*pcur == cur)
286       return false;
287 
288    *val0 = v.uval[0];
289    *val1 = v.uval[1];
290 
291    return true;
292 }
293 
294 struct translate_ctx
295 {
296    const char *text;
297    const char *cur;
298    struct tgsi_token *tokens;
299    struct tgsi_token *tokens_cur;
300    struct tgsi_token *tokens_end;
301    struct tgsi_header *header;
302    unsigned processor : 4;
303    unsigned implied_array_size : 6;
304    unsigned num_immediates;
305 };
306 
report_error(struct translate_ctx * ctx,const char * msg)307 static void report_error( struct translate_ctx *ctx, const char *msg )
308 {
309    int line = 1;
310    int column = 1;
311    const char *itr = ctx->text;
312 
313    while (itr != ctx->cur) {
314       if (*itr == '\n') {
315          column = 1;
316          ++line;
317       }
318       ++column;
319       ++itr;
320    }
321 
322    debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
323 }
324 
325 /* Parse shader header.
326  * Return TRUE for one of the following headers.
327  *    FRAG
328  *    GEOM
329  *    VERT
330  */
parse_header(struct translate_ctx * ctx)331 static bool parse_header( struct translate_ctx *ctx )
332 {
333    enum pipe_shader_type processor;
334 
335    if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
336       processor = PIPE_SHADER_FRAGMENT;
337    else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
338       processor = PIPE_SHADER_VERTEX;
339    else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
340       processor = PIPE_SHADER_GEOMETRY;
341    else if (str_match_nocase_whole( &ctx->cur, "TESS_CTRL" ))
342       processor = PIPE_SHADER_TESS_CTRL;
343    else if (str_match_nocase_whole( &ctx->cur, "TESS_EVAL" ))
344       processor = PIPE_SHADER_TESS_EVAL;
345    else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
346       processor = PIPE_SHADER_COMPUTE;
347    else {
348       report_error( ctx, "Unknown header" );
349       return false;
350    }
351 
352    if (ctx->tokens_cur >= ctx->tokens_end)
353       return false;
354    ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
355    *ctx->header = tgsi_build_header();
356 
357    if (ctx->tokens_cur >= ctx->tokens_end)
358       return false;
359    *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
360    ctx->processor = processor;
361 
362    return true;
363 }
364 
parse_label(struct translate_ctx * ctx,unsigned * val)365 static bool parse_label( struct translate_ctx *ctx, unsigned *val )
366 {
367    const char *cur = ctx->cur;
368 
369    if (parse_uint( &cur, val )) {
370       eat_opt_white( &cur );
371       if (*cur == ':') {
372          cur++;
373          ctx->cur = cur;
374          return true;
375       }
376    }
377    return false;
378 }
379 
380 static bool
parse_file(const char ** pcur,enum tgsi_file_type * file)381 parse_file( const char **pcur, enum tgsi_file_type *file )
382 {
383    enum tgsi_file_type i;
384 
385    for (i = 0; i < TGSI_FILE_COUNT; i++) {
386       const char *cur = *pcur;
387 
388       if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) {
389          *pcur = cur;
390          *file = i;
391          return true;
392       }
393    }
394    return false;
395 }
396 
397 static bool
parse_opt_writemask(struct translate_ctx * ctx,unsigned * writemask)398 parse_opt_writemask(
399    struct translate_ctx *ctx,
400    unsigned *writemask )
401 {
402    const char *cur;
403 
404    cur = ctx->cur;
405    eat_opt_white( &cur );
406    if (*cur == '.') {
407       cur++;
408       *writemask = TGSI_WRITEMASK_NONE;
409       eat_opt_white( &cur );
410       if (uprcase( *cur ) == 'X') {
411          cur++;
412          *writemask |= TGSI_WRITEMASK_X;
413       }
414       if (uprcase( *cur ) == 'Y') {
415          cur++;
416          *writemask |= TGSI_WRITEMASK_Y;
417       }
418       if (uprcase( *cur ) == 'Z') {
419          cur++;
420          *writemask |= TGSI_WRITEMASK_Z;
421       }
422       if (uprcase( *cur ) == 'W') {
423          cur++;
424          *writemask |= TGSI_WRITEMASK_W;
425       }
426 
427       if (*writemask == TGSI_WRITEMASK_NONE) {
428          report_error( ctx, "Writemask expected" );
429          return false;
430       }
431 
432       ctx->cur = cur;
433    }
434    else {
435       *writemask = TGSI_WRITEMASK_XYZW;
436    }
437    return true;
438 }
439 
440 
441 /* <register_file_bracket> ::= <file> `['
442  */
443 static bool
parse_register_file_bracket(struct translate_ctx * ctx,enum tgsi_file_type * file)444 parse_register_file_bracket(
445    struct translate_ctx *ctx,
446    enum tgsi_file_type *file )
447 {
448    if (!parse_file( &ctx->cur, file )) {
449       report_error( ctx, "Unknown register file" );
450       return false;
451    }
452    eat_opt_white( &ctx->cur );
453    if (*ctx->cur != '[') {
454       report_error( ctx, "Expected `['" );
455       return false;
456    }
457    ctx->cur++;
458    return true;
459 }
460 
461 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
462  */
463 static bool
parse_register_file_bracket_index(struct translate_ctx * ctx,enum tgsi_file_type * file,int * index)464 parse_register_file_bracket_index(
465    struct translate_ctx *ctx,
466    enum tgsi_file_type *file,
467    int *index )
468 {
469    unsigned uindex;
470 
471    if (!parse_register_file_bracket( ctx, file ))
472       return false;
473    eat_opt_white( &ctx->cur );
474    if (!parse_uint( &ctx->cur, &uindex )) {
475       report_error( ctx, "Expected literal unsigned integer" );
476       return false;
477    }
478    *index = (int) uindex;
479    return true;
480 }
481 
482 /* Parse simple 1d register operand.
483  *    <register_dst> ::= <register_file_bracket_index> `]'
484  */
485 static bool
parse_register_1d(struct translate_ctx * ctx,enum tgsi_file_type * file,int * index)486 parse_register_1d(struct translate_ctx *ctx,
487                   enum tgsi_file_type *file,
488                   int *index )
489 {
490    if (!parse_register_file_bracket_index( ctx, file, index ))
491       return false;
492    eat_opt_white( &ctx->cur );
493    if (*ctx->cur != ']') {
494       report_error( ctx, "Expected `]'" );
495       return false;
496    }
497    ctx->cur++;
498    return true;
499 }
500 
501 struct parsed_bracket {
502    int index;
503 
504    enum tgsi_file_type ind_file;
505    int ind_index;
506    unsigned ind_comp;
507    unsigned ind_array;
508 };
509 
510 
511 static bool
parse_register_bracket(struct translate_ctx * ctx,struct parsed_bracket * brackets)512 parse_register_bracket(
513    struct translate_ctx *ctx,
514    struct parsed_bracket *brackets)
515 {
516    const char *cur;
517    unsigned uindex;
518 
519    memset(brackets, 0, sizeof(struct parsed_bracket));
520 
521    eat_opt_white( &ctx->cur );
522 
523    cur = ctx->cur;
524    if (parse_file( &cur, &brackets->ind_file )) {
525       if (!parse_register_1d( ctx, &brackets->ind_file,
526                               &brackets->ind_index ))
527          return false;
528       eat_opt_white( &ctx->cur );
529 
530       if (*ctx->cur == '.') {
531          ctx->cur++;
532          eat_opt_white(&ctx->cur);
533 
534          switch (uprcase(*ctx->cur)) {
535          case 'X':
536             brackets->ind_comp = TGSI_SWIZZLE_X;
537             break;
538          case 'Y':
539             brackets->ind_comp = TGSI_SWIZZLE_Y;
540             break;
541          case 'Z':
542             brackets->ind_comp = TGSI_SWIZZLE_Z;
543             break;
544          case 'W':
545             brackets->ind_comp = TGSI_SWIZZLE_W;
546             break;
547          default:
548             report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
549             return false;
550          }
551          ctx->cur++;
552          eat_opt_white(&ctx->cur);
553       }
554 
555       if (*ctx->cur == '+' || *ctx->cur == '-')
556          parse_int( &ctx->cur, &brackets->index );
557       else
558          brackets->index = 0;
559    }
560    else {
561       if (!parse_uint( &ctx->cur, &uindex )) {
562          report_error( ctx, "Expected literal unsigned integer" );
563          return false;
564       }
565       brackets->index = (int) uindex;
566       brackets->ind_file = TGSI_FILE_NULL;
567       brackets->ind_index = 0;
568    }
569    eat_opt_white( &ctx->cur );
570    if (*ctx->cur != ']') {
571       report_error( ctx, "Expected `]'" );
572       return false;
573    }
574    ctx->cur++;
575    if (*ctx->cur == '(') {
576       ctx->cur++;
577       eat_opt_white( &ctx->cur );
578       if (!parse_uint( &ctx->cur, &brackets->ind_array )) {
579          report_error( ctx, "Expected literal unsigned integer" );
580          return false;
581       }
582       eat_opt_white( &ctx->cur );
583       if (*ctx->cur != ')') {
584          report_error( ctx, "Expected `)'" );
585          return false;
586       }
587       ctx->cur++;
588    }
589    return true;
590 }
591 
592 static bool
parse_opt_register_src_bracket(struct translate_ctx * ctx,struct parsed_bracket * brackets,int * parsed_brackets)593 parse_opt_register_src_bracket(
594    struct translate_ctx *ctx,
595    struct parsed_bracket *brackets,
596    int *parsed_brackets)
597 {
598    const char *cur = ctx->cur;
599 
600    *parsed_brackets = 0;
601 
602    eat_opt_white( &cur );
603    if (cur[0] == '[') {
604       ++cur;
605       ctx->cur = cur;
606 
607       if (!parse_register_bracket(ctx, brackets))
608          return false;
609 
610       *parsed_brackets = 1;
611    }
612 
613    return true;
614 }
615 
616 
617 /* Parse source register operand.
618  *    <register_src> ::= <register_file_bracket_index> `]' |
619  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
620  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
621  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
622  */
623 static bool
parse_register_src(struct translate_ctx * ctx,enum tgsi_file_type * file,struct parsed_bracket * brackets)624 parse_register_src(
625    struct translate_ctx *ctx,
626    enum tgsi_file_type *file,
627    struct parsed_bracket *brackets)
628 {
629    brackets->ind_comp = TGSI_SWIZZLE_X;
630    if (!parse_register_file_bracket( ctx, file ))
631       return false;
632    if (!parse_register_bracket( ctx, brackets ))
633        return false;
634 
635    return true;
636 }
637 
638 struct parsed_dcl_bracket {
639    unsigned first;
640    unsigned last;
641 };
642 
643 static bool
parse_register_dcl_bracket(struct translate_ctx * ctx,struct parsed_dcl_bracket * bracket)644 parse_register_dcl_bracket(
645    struct translate_ctx *ctx,
646    struct parsed_dcl_bracket *bracket)
647 {
648    unsigned uindex;
649    memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
650 
651    eat_opt_white( &ctx->cur );
652 
653    if (!parse_uint( &ctx->cur, &uindex )) {
654       /* it can be an empty bracket [] which means its range
655        * is from 0 to some implied size */
656       if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
657          bracket->first = 0;
658          bracket->last = ctx->implied_array_size - 1;
659          goto cleanup;
660       }
661       report_error( ctx, "Expected literal unsigned integer" );
662       return false;
663    }
664    bracket->first = uindex;
665 
666    eat_opt_white( &ctx->cur );
667 
668    if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
669       unsigned uindex;
670 
671       ctx->cur += 2;
672       eat_opt_white( &ctx->cur );
673       if (!parse_uint( &ctx->cur, &uindex )) {
674          report_error( ctx, "Expected literal integer" );
675          return false;
676       }
677       bracket->last = (int) uindex;
678       eat_opt_white( &ctx->cur );
679    }
680    else {
681       bracket->last = bracket->first;
682    }
683 
684 cleanup:
685    if (*ctx->cur != ']') {
686       report_error( ctx, "Expected `]' or `..'" );
687       return false;
688    }
689    ctx->cur++;
690    return true;
691 }
692 
693 /* Parse register declaration.
694  *    <register_dcl> ::= <register_file_bracket_index> `]' |
695  *                       <register_file_bracket_index> `..' <index> `]'
696  */
697 static bool
parse_register_dcl(struct translate_ctx * ctx,enum tgsi_file_type * file,struct parsed_dcl_bracket * brackets,int * num_brackets)698 parse_register_dcl(
699    struct translate_ctx *ctx,
700    enum tgsi_file_type *file,
701    struct parsed_dcl_bracket *brackets,
702    int *num_brackets)
703 {
704    const char *cur;
705 
706    *num_brackets = 0;
707 
708    if (!parse_register_file_bracket( ctx, file ))
709       return false;
710    if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
711       return false;
712 
713    *num_brackets = 1;
714 
715    cur = ctx->cur;
716    eat_opt_white( &cur );
717 
718    if (cur[0] == '[') {
719       bool is_in = *file == TGSI_FILE_INPUT;
720       bool is_out = *file == TGSI_FILE_OUTPUT;
721 
722       ++cur;
723       ctx->cur = cur;
724       if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
725          return false;
726       /* for geometry shader we don't really care about
727        * the first brackets it's always the size of the
728        * input primitive. so we want to declare just
729        * the index relevant to the semantics which is in
730        * the second bracket */
731 
732       /* tessellation has similar constraints to geometry shader */
733       if ((ctx->processor == PIPE_SHADER_GEOMETRY && is_in) ||
734           (ctx->processor == PIPE_SHADER_TESS_EVAL && is_in) ||
735           (ctx->processor == PIPE_SHADER_TESS_CTRL && (is_in || is_out))) {
736          brackets[0] = brackets[1];
737          *num_brackets = 1;
738       } else {
739          *num_brackets = 2;
740       }
741    }
742 
743    return true;
744 }
745 
746 
747 /* Parse destination register operand.*/
748 static bool
parse_register_dst(struct translate_ctx * ctx,enum tgsi_file_type * file,struct parsed_bracket * brackets)749 parse_register_dst(
750    struct translate_ctx *ctx,
751    enum tgsi_file_type *file,
752    struct parsed_bracket *brackets)
753 {
754    brackets->ind_comp = TGSI_SWIZZLE_X;
755    if (!parse_register_file_bracket( ctx, file ))
756       return false;
757    if (!parse_register_bracket( ctx, brackets ))
758        return false;
759 
760    return true;
761 }
762 
763 static bool
parse_dst_operand(struct translate_ctx * ctx,struct tgsi_full_dst_register * dst)764 parse_dst_operand(
765    struct translate_ctx *ctx,
766    struct tgsi_full_dst_register *dst )
767 {
768    enum tgsi_file_type file;
769    unsigned writemask;
770    const char *cur;
771    struct parsed_bracket bracket[2];
772    int parsed_opt_brackets;
773 
774    if (!parse_register_dst( ctx, &file, &bracket[0] ))
775       return false;
776    if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
777       return false;
778 
779    cur = ctx->cur;
780    eat_opt_white( &cur );
781 
782    if (!parse_opt_writemask( ctx, &writemask ))
783       return false;
784 
785    dst->Register.File = file;
786    if (parsed_opt_brackets) {
787       dst->Register.Dimension = 1;
788       dst->Dimension.Indirect = 0;
789       dst->Dimension.Dimension = 0;
790       dst->Dimension.Index = bracket[0].index;
791 
792       if (bracket[0].ind_file != TGSI_FILE_NULL) {
793          dst->Dimension.Indirect = 1;
794          dst->DimIndirect.File = bracket[0].ind_file;
795          dst->DimIndirect.Index = bracket[0].ind_index;
796          dst->DimIndirect.Swizzle = bracket[0].ind_comp;
797          dst->DimIndirect.ArrayID = bracket[0].ind_array;
798       }
799       bracket[0] = bracket[1];
800    }
801    dst->Register.Index = bracket[0].index;
802    dst->Register.WriteMask = writemask;
803    if (bracket[0].ind_file != TGSI_FILE_NULL) {
804       dst->Register.Indirect = 1;
805       dst->Indirect.File = bracket[0].ind_file;
806       dst->Indirect.Index = bracket[0].ind_index;
807       dst->Indirect.Swizzle = bracket[0].ind_comp;
808       dst->Indirect.ArrayID = bracket[0].ind_array;
809    }
810    return true;
811 }
812 
813 static bool
parse_optional_swizzle(struct translate_ctx * ctx,unsigned * swizzle,bool * parsed_swizzle,int components)814 parse_optional_swizzle(
815    struct translate_ctx *ctx,
816    unsigned *swizzle,
817    bool *parsed_swizzle,
818    int components)
819 {
820    const char *cur = ctx->cur;
821 
822    *parsed_swizzle = false;
823 
824    eat_opt_white( &cur );
825    if (*cur == '.') {
826       int i;
827 
828       cur++;
829       eat_opt_white( &cur );
830       for (i = 0; i < components; i++) {
831          if (uprcase( *cur ) == 'X')
832             swizzle[i] = TGSI_SWIZZLE_X;
833          else if (uprcase( *cur ) == 'Y')
834             swizzle[i] = TGSI_SWIZZLE_Y;
835          else if (uprcase( *cur ) == 'Z')
836             swizzle[i] = TGSI_SWIZZLE_Z;
837          else if (uprcase( *cur ) == 'W')
838             swizzle[i] = TGSI_SWIZZLE_W;
839          else {
840 	    report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
841 	    return false;
842          }
843          cur++;
844       }
845       *parsed_swizzle = true;
846       ctx->cur = cur;
847    }
848    return true;
849 }
850 
851 static bool
parse_src_operand(struct translate_ctx * ctx,struct tgsi_full_src_register * src)852 parse_src_operand(
853    struct translate_ctx *ctx,
854    struct tgsi_full_src_register *src )
855 {
856    enum tgsi_file_type file;
857    unsigned swizzle[4];
858    bool parsed_swizzle;
859    struct parsed_bracket bracket[2];
860    int parsed_opt_brackets;
861 
862    if (*ctx->cur == '-') {
863       ctx->cur++;
864       eat_opt_white( &ctx->cur );
865       src->Register.Negate = 1;
866    }
867 
868    if (*ctx->cur == '|') {
869       ctx->cur++;
870       eat_opt_white( &ctx->cur );
871       src->Register.Absolute = 1;
872    }
873 
874    if (!parse_register_src(ctx, &file, &bracket[0]))
875       return false;
876    if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
877       return false;
878 
879    src->Register.File = file;
880    if (parsed_opt_brackets) {
881       src->Register.Dimension = 1;
882       src->Dimension.Indirect = 0;
883       src->Dimension.Dimension = 0;
884       src->Dimension.Index = bracket[0].index;
885       if (bracket[0].ind_file != TGSI_FILE_NULL) {
886          src->Dimension.Indirect = 1;
887          src->DimIndirect.File = bracket[0].ind_file;
888          src->DimIndirect.Index = bracket[0].ind_index;
889          src->DimIndirect.Swizzle = bracket[0].ind_comp;
890          src->DimIndirect.ArrayID = bracket[0].ind_array;
891       }
892       bracket[0] = bracket[1];
893    }
894    src->Register.Index = bracket[0].index;
895    if (bracket[0].ind_file != TGSI_FILE_NULL) {
896       src->Register.Indirect = 1;
897       src->Indirect.File = bracket[0].ind_file;
898       src->Indirect.Index = bracket[0].ind_index;
899       src->Indirect.Swizzle = bracket[0].ind_comp;
900       src->Indirect.ArrayID = bracket[0].ind_array;
901    }
902 
903    /* Parse optional swizzle.
904     */
905    if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) {
906       if (parsed_swizzle) {
907          src->Register.SwizzleX = swizzle[0];
908          src->Register.SwizzleY = swizzle[1];
909          src->Register.SwizzleZ = swizzle[2];
910          src->Register.SwizzleW = swizzle[3];
911       }
912    }
913 
914    if (src->Register.Absolute) {
915       eat_opt_white( &ctx->cur );
916       if (*ctx->cur != '|') {
917          report_error( ctx, "Expected `|'" );
918          return false;
919       }
920       ctx->cur++;
921    }
922 
923 
924    return true;
925 }
926 
927 static bool
parse_texoffset_operand(struct translate_ctx * ctx,struct tgsi_texture_offset * src)928 parse_texoffset_operand(
929    struct translate_ctx *ctx,
930    struct tgsi_texture_offset *src )
931 {
932    enum tgsi_file_type file;
933    unsigned swizzle[3];
934    bool parsed_swizzle;
935    struct parsed_bracket bracket;
936 
937    if (!parse_register_src(ctx, &file, &bracket))
938       return false;
939 
940    src->File = file;
941    src->Index = bracket.index;
942 
943    /* Parse optional swizzle.
944     */
945    if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) {
946       if (parsed_swizzle) {
947          src->SwizzleX = swizzle[0];
948          src->SwizzleY = swizzle[1];
949          src->SwizzleZ = swizzle[2];
950       }
951    }
952 
953    return true;
954 }
955 
956 static bool
match_inst(const char ** pcur,unsigned * saturate,unsigned * precise,const struct tgsi_opcode_info * info)957 match_inst(const char **pcur,
958            unsigned *saturate,
959            unsigned *precise,
960            const struct tgsi_opcode_info *info)
961 {
962    const char *cur = *pcur;
963    const char *mnemonic = tgsi_get_opcode_name(info->opcode);
964 
965    /* simple case: the whole string matches the instruction name */
966    if (str_match_nocase_whole(&cur, mnemonic)) {
967       *pcur = cur;
968       *saturate = 0;
969       *precise = 0;
970       return true;
971    }
972 
973    if (str_match_no_case(&cur, mnemonic)) {
974       /* the instruction has a suffix, figure it out */
975       if (str_match_no_case(&cur, "_SAT")) {
976          *pcur = cur;
977          *saturate = 1;
978       }
979 
980       if (str_match_no_case(&cur, "_PRECISE")) {
981          *pcur = cur;
982          *precise = 1;
983       }
984 
985       if (!is_digit_alpha_underscore(cur))
986          return true;
987    }
988 
989    return false;
990 }
991 
992 static bool
parse_instruction(struct translate_ctx * ctx,bool has_label)993 parse_instruction(
994    struct translate_ctx *ctx,
995    bool has_label )
996 {
997    int i;
998    unsigned saturate = 0;
999    unsigned precise = 0;
1000    const struct tgsi_opcode_info *info;
1001    struct tgsi_full_instruction inst;
1002    const char *cur;
1003    unsigned advance;
1004 
1005    inst = tgsi_default_full_instruction();
1006 
1007    /* Parse instruction name.
1008     */
1009    eat_opt_white( &ctx->cur );
1010    for (i = 0; i < TGSI_OPCODE_LAST; i++) {
1011       cur = ctx->cur;
1012 
1013       info = tgsi_get_opcode_info( i );
1014       if (match_inst(&cur, &saturate, &precise, info)) {
1015          if (info->num_dst + info->num_src + info->is_tex == 0) {
1016             ctx->cur = cur;
1017             break;
1018          }
1019          else if (*cur == '\0' || eat_white( &cur )) {
1020             ctx->cur = cur;
1021             break;
1022          }
1023       }
1024    }
1025    if (i == TGSI_OPCODE_LAST) {
1026       if (has_label)
1027          report_error( ctx, "Unknown opcode" );
1028       else
1029          report_error( ctx, "Expected `DCL', `IMM' or a label" );
1030       return false;
1031    }
1032 
1033    inst.Instruction.Opcode = i;
1034    inst.Instruction.Saturate = saturate;
1035    inst.Instruction.Precise = precise;
1036    inst.Instruction.NumDstRegs = info->num_dst;
1037    inst.Instruction.NumSrcRegs = info->num_src;
1038 
1039    if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
1040       /*
1041        * These are not considered tex opcodes here (no additional
1042        * target argument) however we're required to set the Texture
1043        * bit so we can set the number of tex offsets.
1044        */
1045       inst.Instruction.Texture = 1;
1046       inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
1047    }
1048 
1049    if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) ||
1050        i == TGSI_OPCODE_RESQ) {
1051       inst.Instruction.Memory = 1;
1052       inst.Memory.Qualifier = 0;
1053    }
1054 
1055    assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS);
1056    assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS);
1057 
1058    /* Parse instruction operands.
1059     */
1060    for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
1061       if (i > 0) {
1062          eat_opt_white( &ctx->cur );
1063          if (*ctx->cur != ',') {
1064             report_error( ctx, "Expected `,'" );
1065             return false;
1066          }
1067          ctx->cur++;
1068          eat_opt_white( &ctx->cur );
1069       }
1070 
1071       if (i < info->num_dst) {
1072          if (!parse_dst_operand( ctx, &inst.Dst[i] ))
1073             return false;
1074       }
1075       else if (i < info->num_dst + info->num_src) {
1076          if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
1077             return false;
1078       }
1079       else {
1080          unsigned j;
1081 
1082          for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
1083             if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
1084                inst.Instruction.Texture = 1;
1085                inst.Texture.Texture = j;
1086                break;
1087             }
1088          }
1089          if (j == TGSI_TEXTURE_COUNT) {
1090             report_error( ctx, "Expected texture target" );
1091             return false;
1092          }
1093       }
1094    }
1095 
1096    cur = ctx->cur;
1097    eat_opt_white( &cur );
1098    for (i = 0; inst.Instruction.Texture && *cur == ',' && i < TGSI_FULL_MAX_TEX_OFFSETS; i++) {
1099          cur++;
1100          eat_opt_white( &cur );
1101          ctx->cur = cur;
1102          if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] ))
1103             return false;
1104          cur = ctx->cur;
1105          eat_opt_white( &cur );
1106    }
1107    inst.Texture.NumOffsets = i;
1108 
1109    cur = ctx->cur;
1110    eat_opt_white(&cur);
1111 
1112    for (; inst.Instruction.Memory && *cur == ',';
1113         ctx->cur = cur, eat_opt_white(&cur)) {
1114       int j;
1115 
1116       cur++;
1117       eat_opt_white(&cur);
1118 
1119       j = str_match_name_from_array(&cur, tgsi_memory_names,
1120                                     ARRAY_SIZE(tgsi_memory_names));
1121       if (j >= 0) {
1122          inst.Memory.Qualifier |= 1U << j;
1123          continue;
1124       }
1125 
1126       j = str_match_name_from_array(&cur, tgsi_texture_names,
1127                                     ARRAY_SIZE(tgsi_texture_names));
1128       if (j >= 0) {
1129          inst.Memory.Texture = j;
1130          continue;
1131       }
1132 
1133       j = str_match_format(&cur);
1134       if (j >= 0) {
1135          inst.Memory.Format = j;
1136          continue;
1137       }
1138 
1139       ctx->cur = cur;
1140       report_error(ctx, "Expected memory qualifier, texture target, or format\n");
1141       return false;
1142    }
1143 
1144    cur = ctx->cur;
1145    eat_opt_white( &cur );
1146    if (info->is_branch && *cur == ':') {
1147       unsigned target;
1148 
1149       cur++;
1150       eat_opt_white( &cur );
1151       if (!parse_uint( &cur, &target )) {
1152          report_error( ctx, "Expected a label" );
1153          return false;
1154       }
1155       inst.Instruction.Label = 1;
1156       inst.Label.Label = target;
1157       ctx->cur = cur;
1158    }
1159 
1160    advance = tgsi_build_full_instruction(
1161       &inst,
1162       ctx->tokens_cur,
1163       ctx->header,
1164       (unsigned) (ctx->tokens_end - ctx->tokens_cur) );
1165    if (advance == 0)
1166       return false;
1167    ctx->tokens_cur += advance;
1168 
1169    return true;
1170 }
1171 
1172 /* parses a 4-touple of the form {x, y, z, w}
1173  * where x, y, z, w are numbers */
parse_immediate_data(struct translate_ctx * ctx,unsigned type,union tgsi_immediate_data * values)1174 static bool parse_immediate_data(struct translate_ctx *ctx, unsigned type,
1175                                  union tgsi_immediate_data *values)
1176 {
1177    unsigned i;
1178    int ret;
1179 
1180    eat_opt_white( &ctx->cur );
1181    if (*ctx->cur != '{') {
1182       report_error( ctx, "Expected `{'" );
1183       return false;
1184    }
1185    ctx->cur++;
1186    for (i = 0; i < 4; i++) {
1187       eat_opt_white( &ctx->cur );
1188       if (i > 0) {
1189          if (*ctx->cur != ',') {
1190             report_error( ctx, "Expected `,'" );
1191             return false;
1192          }
1193          ctx->cur++;
1194          eat_opt_white( &ctx->cur );
1195       }
1196 
1197       switch (type) {
1198       case TGSI_IMM_FLOAT64:
1199          ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
1200          i++;
1201          break;
1202       case TGSI_IMM_INT64:
1203          ret = parse_int64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
1204          i++;
1205          break;
1206       case TGSI_IMM_UINT64:
1207          ret = parse_uint64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
1208          i++;
1209          break;
1210       case TGSI_IMM_FLOAT32:
1211          ret = parse_float(&ctx->cur, &values[i].Float);
1212          break;
1213       case TGSI_IMM_UINT32:
1214          ret = parse_uint(&ctx->cur, &values[i].Uint);
1215          break;
1216       case TGSI_IMM_INT32:
1217          ret = parse_int(&ctx->cur, &values[i].Int);
1218          break;
1219       default:
1220          assert(0);
1221          ret = false;
1222          break;
1223       }
1224 
1225       if (!ret) {
1226          report_error( ctx, "Expected immediate constant" );
1227          return false;
1228       }
1229    }
1230    eat_opt_white( &ctx->cur );
1231    if (*ctx->cur != '}') {
1232       report_error( ctx, "Expected `}'" );
1233       return false;
1234    }
1235    ctx->cur++;
1236 
1237    return true;
1238 }
1239 
parse_declaration(struct translate_ctx * ctx)1240 static bool parse_declaration( struct translate_ctx *ctx )
1241 {
1242    struct tgsi_full_declaration decl;
1243    enum tgsi_file_type file;
1244    struct parsed_dcl_bracket brackets[2];
1245    int num_brackets;
1246    unsigned writemask;
1247    const char *cur, *cur2;
1248    unsigned advance;
1249    bool is_vs_input;
1250 
1251    if (!eat_white( &ctx->cur )) {
1252       report_error( ctx, "Syntax error" );
1253       return false;
1254    }
1255    if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1256       return false;
1257    if (!parse_opt_writemask( ctx, &writemask ))
1258       return false;
1259 
1260    decl = tgsi_default_full_declaration();
1261    decl.Declaration.File = file;
1262    decl.Declaration.UsageMask = writemask;
1263 
1264    if (num_brackets == 1) {
1265       decl.Range.First = brackets[0].first;
1266       decl.Range.Last = brackets[0].last;
1267    } else {
1268       decl.Range.First = brackets[1].first;
1269       decl.Range.Last = brackets[1].last;
1270 
1271       decl.Declaration.Dimension = 1;
1272       decl.Dim.Index2D = brackets[0].first;
1273    }
1274 
1275    is_vs_input = (file == TGSI_FILE_INPUT &&
1276                   ctx->processor == PIPE_SHADER_VERTEX);
1277 
1278    cur = ctx->cur;
1279    eat_opt_white( &cur );
1280    if (*cur == ',') {
1281       cur2 = cur;
1282       cur2++;
1283       eat_opt_white( &cur2 );
1284       if (str_match_nocase_whole( &cur2, "ARRAY" )) {
1285          int arrayid;
1286          if (*cur2 != '(') {
1287             report_error( ctx, "Expected `('" );
1288             return false;
1289          }
1290          cur2++;
1291          eat_opt_white( &cur2 );
1292          if (!parse_int( &cur2, &arrayid )) {
1293             report_error( ctx, "Expected `,'" );
1294             return false;
1295          }
1296          eat_opt_white( &cur2 );
1297          if (*cur2 != ')') {
1298             report_error( ctx, "Expected `)'" );
1299             return false;
1300          }
1301          cur2++;
1302          decl.Declaration.Array = 1;
1303          decl.Array.ArrayID = arrayid;
1304          ctx->cur = cur = cur2;
1305       }
1306    }
1307 
1308    if (*cur == ',' && !is_vs_input) {
1309       unsigned i, j;
1310 
1311       cur++;
1312       eat_opt_white( &cur );
1313       if (file == TGSI_FILE_IMAGE) {
1314          for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1315             if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1316                decl.Image.Resource = i;
1317                break;
1318             }
1319          }
1320          if (i == TGSI_TEXTURE_COUNT) {
1321             report_error(ctx, "Expected texture target");
1322             return false;
1323          }
1324 
1325          cur2 = cur;
1326          eat_opt_white(&cur2);
1327          while (*cur2 == ',') {
1328             cur2++;
1329             eat_opt_white(&cur2);
1330             if (str_match_nocase_whole(&cur2, "RAW")) {
1331                decl.Image.Raw = 1;
1332 
1333             } else if (str_match_nocase_whole(&cur2, "WR")) {
1334                decl.Image.Writable = 1;
1335 
1336             } else {
1337                int format = str_match_format(&cur2);
1338                if (format < 0)
1339                   break;
1340 
1341                decl.Image.Format = format;
1342             }
1343             cur = cur2;
1344             eat_opt_white(&cur2);
1345          }
1346 
1347          ctx->cur = cur;
1348 
1349       } else if (file == TGSI_FILE_SAMPLER_VIEW) {
1350          for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1351             if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1352                decl.SamplerView.Resource = i;
1353                break;
1354             }
1355          }
1356          if (i == TGSI_TEXTURE_COUNT) {
1357             report_error(ctx, "Expected texture target");
1358             return false;
1359          }
1360          eat_opt_white( &cur );
1361          if (*cur != ',') {
1362             report_error( ctx, "Expected `,'" );
1363             return false;
1364          }
1365          ++cur;
1366          eat_opt_white( &cur );
1367          for (j = 0; j < 4; ++j) {
1368             for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) {
1369                if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) {
1370                   switch (j) {
1371                   case 0:
1372                      decl.SamplerView.ReturnTypeX = i;
1373                      break;
1374                   case 1:
1375                      decl.SamplerView.ReturnTypeY = i;
1376                      break;
1377                   case 2:
1378                      decl.SamplerView.ReturnTypeZ = i;
1379                      break;
1380                   case 3:
1381                      decl.SamplerView.ReturnTypeW = i;
1382                      break;
1383                   default:
1384                      assert(0);
1385                   }
1386                   break;
1387                }
1388             }
1389             if (i == TGSI_RETURN_TYPE_COUNT) {
1390                if (j == 0 || j >  2) {
1391                   report_error(ctx, "Expected type name");
1392                   return false;
1393                }
1394                break;
1395             } else {
1396                cur2 = cur;
1397                eat_opt_white( &cur2 );
1398                if (*cur2 == ',') {
1399                   cur2++;
1400                   eat_opt_white( &cur2 );
1401                   cur = cur2;
1402                   continue;
1403                } else
1404                   break;
1405             }
1406          }
1407          if (j < 4) {
1408             decl.SamplerView.ReturnTypeY =
1409                decl.SamplerView.ReturnTypeZ =
1410                decl.SamplerView.ReturnTypeW =
1411                decl.SamplerView.ReturnTypeX;
1412          }
1413          ctx->cur = cur;
1414       } else if (file == TGSI_FILE_BUFFER) {
1415          if (str_match_nocase_whole(&cur, "ATOMIC")) {
1416             decl.Declaration.Atomic = 1;
1417             ctx->cur = cur;
1418          }
1419       } else if (file == TGSI_FILE_MEMORY) {
1420          if (str_match_nocase_whole(&cur, "GLOBAL")) {
1421             /* Note this is a no-op global is the default */
1422             decl.Declaration.MemType = TGSI_MEMORY_TYPE_GLOBAL;
1423             ctx->cur = cur;
1424          } else if (str_match_nocase_whole(&cur, "SHARED")) {
1425             decl.Declaration.MemType = TGSI_MEMORY_TYPE_SHARED;
1426             ctx->cur = cur;
1427          } else if (str_match_nocase_whole(&cur, "PRIVATE")) {
1428             decl.Declaration.MemType = TGSI_MEMORY_TYPE_PRIVATE;
1429             ctx->cur = cur;
1430          } else if (str_match_nocase_whole(&cur, "INPUT")) {
1431             decl.Declaration.MemType = TGSI_MEMORY_TYPE_INPUT;
1432             ctx->cur = cur;
1433          }
1434       } else {
1435          if (str_match_nocase_whole(&cur, "LOCAL")) {
1436             decl.Declaration.Local = 1;
1437             ctx->cur = cur;
1438          }
1439 
1440          cur = ctx->cur;
1441          eat_opt_white( &cur );
1442          if (*cur == ',') {
1443             cur++;
1444             eat_opt_white( &cur );
1445 
1446             for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1447                if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
1448                   unsigned index;
1449 
1450                   cur2 = cur;
1451                   eat_opt_white( &cur2 );
1452                   if (*cur2 == '[') {
1453                      cur2++;
1454                      eat_opt_white( &cur2 );
1455                      if (!parse_uint( &cur2, &index )) {
1456                         report_error( ctx, "Expected literal integer" );
1457                         return false;
1458                      }
1459                      eat_opt_white( &cur2 );
1460                      if (*cur2 != ']') {
1461                         report_error( ctx, "Expected `]'" );
1462                         return false;
1463                      }
1464                      cur2++;
1465 
1466                      decl.Semantic.Index = index;
1467 
1468                      cur = cur2;
1469                   }
1470 
1471                   decl.Declaration.Semantic = 1;
1472                   decl.Semantic.Name = i;
1473 
1474                   ctx->cur = cur;
1475                   break;
1476                }
1477             }
1478          }
1479       }
1480    }
1481 
1482    cur = ctx->cur;
1483    eat_opt_white( &cur );
1484    if (*cur == ',' &&
1485        file == TGSI_FILE_OUTPUT && ctx->processor == PIPE_SHADER_GEOMETRY) {
1486       cur++;
1487       eat_opt_white(&cur);
1488       if (str_match_nocase_whole(&cur, "STREAM")) {
1489          unsigned stream[4];
1490 
1491          eat_opt_white(&cur);
1492          if (*cur != '(') {
1493             report_error(ctx, "Expected '('");
1494             return false;
1495          }
1496          cur++;
1497 
1498          for (int i = 0; i < 4; ++i) {
1499             eat_opt_white(&cur);
1500             if (!parse_uint(&cur, &stream[i])) {
1501                report_error(ctx, "Expected literal integer");
1502                return false;
1503             }
1504 
1505             eat_opt_white(&cur);
1506             if (i < 3) {
1507                if (*cur != ',') {
1508                   report_error(ctx, "Expected ','");
1509                   return false;
1510                }
1511                cur++;
1512             }
1513          }
1514 
1515          if (*cur != ')') {
1516             report_error(ctx, "Expected ')'");
1517             return false;
1518          }
1519          cur++;
1520 
1521          decl.Semantic.StreamX = stream[0];
1522          decl.Semantic.StreamY = stream[1];
1523          decl.Semantic.StreamZ = stream[2];
1524          decl.Semantic.StreamW = stream[3];
1525 
1526          ctx->cur = cur;
1527       }
1528    }
1529 
1530    cur = ctx->cur;
1531    eat_opt_white( &cur );
1532    if (*cur == ',' && !is_vs_input) {
1533       unsigned i;
1534 
1535       cur++;
1536       eat_opt_white( &cur );
1537       for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1538          if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
1539             decl.Declaration.Interpolate = 1;
1540             decl.Interp.Interpolate = i;
1541 
1542             ctx->cur = cur;
1543             break;
1544          }
1545       }
1546    }
1547 
1548    cur = ctx->cur;
1549    eat_opt_white( &cur );
1550    if (*cur == ',' && !is_vs_input) {
1551       unsigned i;
1552 
1553       cur++;
1554       eat_opt_white( &cur );
1555       for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) {
1556          if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) {
1557             decl.Interp.Location = i;
1558 
1559             ctx->cur = cur;
1560             break;
1561          }
1562       }
1563    }
1564 
1565    cur = ctx->cur;
1566    eat_opt_white( &cur );
1567    if (*cur == ',' && !is_vs_input) {
1568       cur++;
1569       eat_opt_white( &cur );
1570       if (str_match_nocase_whole( &cur, tgsi_invariant_name )) {
1571          decl.Declaration.Invariant = 1;
1572          ctx->cur = cur;
1573       } else {
1574          report_error( ctx, "Expected semantic, interpolate attribute, or invariant ");
1575          return false;
1576       }
1577    }
1578 
1579    advance = tgsi_build_full_declaration(
1580       &decl,
1581       ctx->tokens_cur,
1582       ctx->header,
1583       (unsigned) (ctx->tokens_end - ctx->tokens_cur) );
1584 
1585    if (advance == 0)
1586       return false;
1587    ctx->tokens_cur += advance;
1588 
1589    return true;
1590 }
1591 
parse_immediate(struct translate_ctx * ctx)1592 static bool parse_immediate( struct translate_ctx *ctx )
1593 {
1594    struct tgsi_full_immediate imm;
1595    unsigned advance;
1596    unsigned type;
1597 
1598    if (*ctx->cur == '[') {
1599       unsigned uindex;
1600 
1601       ++ctx->cur;
1602 
1603       eat_opt_white( &ctx->cur );
1604       if (!parse_uint( &ctx->cur, &uindex )) {
1605          report_error( ctx, "Expected literal unsigned integer" );
1606          return false;
1607       }
1608 
1609       if (uindex != ctx->num_immediates) {
1610          report_error( ctx, "Immediates must be sorted" );
1611          return false;
1612       }
1613 
1614       eat_opt_white( &ctx->cur );
1615       if (*ctx->cur != ']') {
1616          report_error( ctx, "Expected `]'" );
1617          return false;
1618       }
1619 
1620       ctx->cur++;
1621    }
1622 
1623    if (!eat_white( &ctx->cur )) {
1624       report_error( ctx, "Syntax error" );
1625       return false;
1626    }
1627    for (type = 0; type < ARRAY_SIZE(tgsi_immediate_type_names); ++type) {
1628       if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
1629          break;
1630    }
1631    if (type == ARRAY_SIZE(tgsi_immediate_type_names)) {
1632       report_error( ctx, "Expected immediate type" );
1633       return false;
1634    }
1635 
1636    imm = tgsi_default_full_immediate();
1637    imm.Immediate.NrTokens += 4;
1638    imm.Immediate.DataType = type;
1639    parse_immediate_data(ctx, type, imm.u);
1640 
1641    advance = tgsi_build_full_immediate(
1642       &imm,
1643       ctx->tokens_cur,
1644       ctx->header,
1645       (unsigned) (ctx->tokens_end - ctx->tokens_cur) );
1646    if (advance == 0)
1647       return false;
1648    ctx->tokens_cur += advance;
1649 
1650    ctx->num_immediates++;
1651 
1652    return true;
1653 }
1654 
1655 static bool
parse_primitive(const char ** pcur,unsigned * primitive)1656 parse_primitive( const char **pcur, unsigned *primitive )
1657 {
1658    unsigned i;
1659 
1660    for (i = 0; i < MESA_PRIM_COUNT; i++) {
1661       const char *cur = *pcur;
1662 
1663       if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
1664          *primitive = i;
1665          *pcur = cur;
1666          return true;
1667       }
1668    }
1669    return false;
1670 }
1671 
1672 static bool
parse_fs_coord_origin(const char ** pcur,unsigned * fs_coord_origin)1673 parse_fs_coord_origin( const char **pcur, unsigned *fs_coord_origin )
1674 {
1675    unsigned i;
1676 
1677    for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_origin_names); i++) {
1678       const char *cur = *pcur;
1679 
1680       if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
1681          *fs_coord_origin = i;
1682          *pcur = cur;
1683          return true;
1684       }
1685    }
1686    return false;
1687 }
1688 
1689 static bool
parse_fs_coord_pixel_center(const char ** pcur,unsigned * fs_coord_pixel_center)1690 parse_fs_coord_pixel_center( const char **pcur, unsigned *fs_coord_pixel_center )
1691 {
1692    unsigned i;
1693 
1694    for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_pixel_center_names); i++) {
1695       const char *cur = *pcur;
1696 
1697       if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
1698          *fs_coord_pixel_center = i;
1699          *pcur = cur;
1700          return true;
1701       }
1702    }
1703    return false;
1704 }
1705 
1706 static bool
parse_property_next_shader(const char ** pcur,unsigned * next_shader)1707 parse_property_next_shader( const char **pcur, unsigned *next_shader )
1708 {
1709    unsigned i;
1710 
1711    for (i = 0; i < ARRAY_SIZE(tgsi_processor_type_names); i++) {
1712       const char *cur = *pcur;
1713 
1714       if (str_match_nocase_whole( &cur, tgsi_processor_type_names[i])) {
1715          *next_shader = i;
1716          *pcur = cur;
1717          return true;
1718       }
1719    }
1720    return false;
1721 }
1722 
parse_property(struct translate_ctx * ctx)1723 static bool parse_property( struct translate_ctx *ctx )
1724 {
1725    struct tgsi_full_property prop;
1726    enum tgsi_property_name property_name;
1727    unsigned values[8];
1728    unsigned advance;
1729    char id[64];
1730 
1731    if (!eat_white( &ctx->cur )) {
1732       report_error( ctx, "Syntax error" );
1733       return false;
1734    }
1735    if (!parse_identifier( &ctx->cur, id, sizeof(id) )) {
1736       report_error( ctx, "Syntax error" );
1737       return false;
1738    }
1739    for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1740         ++property_name) {
1741       if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
1742          break;
1743       }
1744    }
1745    if (property_name >= TGSI_PROPERTY_COUNT) {
1746       debug_printf( "\nError: Unknown property : '%s'", id );
1747       return false;
1748    }
1749 
1750    eat_opt_white( &ctx->cur );
1751    switch(property_name) {
1752    case TGSI_PROPERTY_GS_INPUT_PRIM:
1753    case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1754       if (!parse_primitive(&ctx->cur, &values[0] )) {
1755          report_error( ctx, "Unknown primitive name as property!" );
1756          return false;
1757       }
1758       if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1759           ctx->processor == PIPE_SHADER_GEOMETRY) {
1760          ctx->implied_array_size = mesa_vertices_per_prim(values[0]);
1761       }
1762       break;
1763    case TGSI_PROPERTY_FS_COORD_ORIGIN:
1764       if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1765          report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1766          return false;
1767       }
1768       break;
1769    case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1770       if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1771          report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1772          return false;
1773       }
1774       break;
1775    case TGSI_PROPERTY_NEXT_SHADER:
1776       if (!parse_property_next_shader(&ctx->cur, &values[0] )) {
1777          report_error( ctx, "Unknown next shader property value." );
1778          return false;
1779       }
1780       break;
1781    case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
1782    default:
1783       if (!parse_uint(&ctx->cur, &values[0] )) {
1784          report_error( ctx, "Expected unsigned integer as property!" );
1785          return false;
1786       }
1787    }
1788 
1789    prop = tgsi_default_full_property();
1790    prop.Property.PropertyName = property_name;
1791    prop.Property.NrTokens += 1;
1792    prop.u[0].Data = values[0];
1793 
1794    advance = tgsi_build_full_property(
1795       &prop,
1796       ctx->tokens_cur,
1797       ctx->header,
1798       (unsigned) (ctx->tokens_end - ctx->tokens_cur) );
1799    if (advance == 0)
1800       return false;
1801    ctx->tokens_cur += advance;
1802 
1803    return true;
1804 }
1805 
1806 
translate(struct translate_ctx * ctx)1807 static bool translate( struct translate_ctx *ctx )
1808 {
1809    eat_opt_white( &ctx->cur );
1810    if (!parse_header( ctx ))
1811       return false;
1812 
1813    if (ctx->processor == PIPE_SHADER_TESS_CTRL ||
1814        ctx->processor == PIPE_SHADER_TESS_EVAL)
1815        ctx->implied_array_size = 32;
1816 
1817    while (*ctx->cur != '\0') {
1818       unsigned label_val = 0;
1819       if (!eat_white( &ctx->cur )) {
1820          report_error( ctx, "Syntax error" );
1821          return false;
1822       }
1823 
1824       if (*ctx->cur == '\0')
1825          break;
1826       if (parse_label( ctx, &label_val )) {
1827          if (!parse_instruction( ctx, true ))
1828             return false;
1829       }
1830       else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
1831          if (!parse_declaration( ctx ))
1832             return false;
1833       }
1834       else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
1835          if (!parse_immediate( ctx ))
1836             return false;
1837       }
1838       else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
1839          if (!parse_property( ctx ))
1840             return false;
1841       }
1842       else if (!parse_instruction( ctx, false )) {
1843          return false;
1844       }
1845    }
1846 
1847    return true;
1848 }
1849 
1850 bool
tgsi_text_translate(const char * text,struct tgsi_token * tokens,unsigned num_tokens)1851 tgsi_text_translate(
1852    const char *text,
1853    struct tgsi_token *tokens,
1854    unsigned num_tokens )
1855 {
1856    struct translate_ctx ctx = {0};
1857 
1858    ctx.text = text;
1859    ctx.cur = text;
1860    ctx.tokens = tokens;
1861    ctx.tokens_cur = tokens;
1862    ctx.tokens_end = tokens + num_tokens;
1863 
1864    if (!translate( &ctx ))
1865       return false;
1866 
1867    return tgsi_sanity_check( tokens );
1868 }
1869