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