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