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