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