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