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