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