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