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