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