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