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