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