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