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