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