gallium/tgsi: Introduce the compute processor.
[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 if (str_match_no_case( &ctx->cur, "COMP" ))
242 processor = TGSI_PROCESSOR_COMPUTE;
243 else {
244 report_error( ctx, "Unknown header" );
245 return FALSE;
246 }
247
248 if (ctx->tokens_cur >= ctx->tokens_end)
249 return FALSE;
250 ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
251 *ctx->header = tgsi_build_header();
252
253 if (ctx->tokens_cur >= ctx->tokens_end)
254 return FALSE;
255 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
256 ctx->processor = processor;
257
258 return TRUE;
259 }
260
261 static boolean parse_label( struct translate_ctx *ctx, uint *val )
262 {
263 const char *cur = ctx->cur;
264
265 if (parse_uint( &cur, val )) {
266 eat_opt_white( &cur );
267 if (*cur == ':') {
268 cur++;
269 ctx->cur = cur;
270 return TRUE;
271 }
272 }
273 return FALSE;
274 }
275
276 static boolean
277 parse_file( const char **pcur, uint *file )
278 {
279 uint i;
280
281 for (i = 0; i < TGSI_FILE_COUNT; i++) {
282 const char *cur = *pcur;
283
284 if (str_match_no_case( &cur, tgsi_file_names[i] )) {
285 if (!is_digit_alpha_underscore( cur )) {
286 *pcur = cur;
287 *file = i;
288 return TRUE;
289 }
290 }
291 }
292 return FALSE;
293 }
294
295 static boolean
296 parse_opt_writemask(
297 struct translate_ctx *ctx,
298 uint *writemask )
299 {
300 const char *cur;
301
302 cur = ctx->cur;
303 eat_opt_white( &cur );
304 if (*cur == '.') {
305 cur++;
306 *writemask = TGSI_WRITEMASK_NONE;
307 eat_opt_white( &cur );
308 if (uprcase( *cur ) == 'X') {
309 cur++;
310 *writemask |= TGSI_WRITEMASK_X;
311 }
312 if (uprcase( *cur ) == 'Y') {
313 cur++;
314 *writemask |= TGSI_WRITEMASK_Y;
315 }
316 if (uprcase( *cur ) == 'Z') {
317 cur++;
318 *writemask |= TGSI_WRITEMASK_Z;
319 }
320 if (uprcase( *cur ) == 'W') {
321 cur++;
322 *writemask |= TGSI_WRITEMASK_W;
323 }
324
325 if (*writemask == TGSI_WRITEMASK_NONE) {
326 report_error( ctx, "Writemask expected" );
327 return FALSE;
328 }
329
330 ctx->cur = cur;
331 }
332 else {
333 *writemask = TGSI_WRITEMASK_XYZW;
334 }
335 return TRUE;
336 }
337
338
339 /* <register_file_bracket> ::= <file> `['
340 */
341 static boolean
342 parse_register_file_bracket(
343 struct translate_ctx *ctx,
344 uint *file )
345 {
346 if (!parse_file( &ctx->cur, file )) {
347 report_error( ctx, "Unknown register file" );
348 return FALSE;
349 }
350 eat_opt_white( &ctx->cur );
351 if (*ctx->cur != '[') {
352 report_error( ctx, "Expected `['" );
353 return FALSE;
354 }
355 ctx->cur++;
356 return TRUE;
357 }
358
359 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
360 */
361 static boolean
362 parse_register_file_bracket_index(
363 struct translate_ctx *ctx,
364 uint *file,
365 int *index )
366 {
367 uint uindex;
368
369 if (!parse_register_file_bracket( ctx, file ))
370 return FALSE;
371 eat_opt_white( &ctx->cur );
372 if (!parse_uint( &ctx->cur, &uindex )) {
373 report_error( ctx, "Expected literal unsigned integer" );
374 return FALSE;
375 }
376 *index = (int) uindex;
377 return TRUE;
378 }
379
380 /* Parse simple 1d register operand.
381 * <register_dst> ::= <register_file_bracket_index> `]'
382 */
383 static boolean
384 parse_register_1d(struct translate_ctx *ctx,
385 uint *file,
386 int *index )
387 {
388 if (!parse_register_file_bracket_index( ctx, file, index ))
389 return FALSE;
390 eat_opt_white( &ctx->cur );
391 if (*ctx->cur != ']') {
392 report_error( ctx, "Expected `]'" );
393 return FALSE;
394 }
395 ctx->cur++;
396 return TRUE;
397 }
398
399 struct parsed_bracket {
400 int index;
401
402 uint ind_file;
403 int ind_index;
404 uint ind_comp;
405 };
406
407
408 static boolean
409 parse_register_bracket(
410 struct translate_ctx *ctx,
411 struct parsed_bracket *brackets)
412 {
413 const char *cur;
414 uint uindex;
415
416 memset(brackets, 0, sizeof(struct parsed_bracket));
417
418 eat_opt_white( &ctx->cur );
419
420 cur = ctx->cur;
421 if (parse_file( &cur, &brackets->ind_file )) {
422 if (!parse_register_1d( ctx, &brackets->ind_file,
423 &brackets->ind_index ))
424 return FALSE;
425 eat_opt_white( &ctx->cur );
426
427 if (*ctx->cur == '.') {
428 ctx->cur++;
429 eat_opt_white(&ctx->cur);
430
431 switch (uprcase(*ctx->cur)) {
432 case 'X':
433 brackets->ind_comp = TGSI_SWIZZLE_X;
434 break;
435 case 'Y':
436 brackets->ind_comp = TGSI_SWIZZLE_Y;
437 break;
438 case 'Z':
439 brackets->ind_comp = TGSI_SWIZZLE_Z;
440 break;
441 case 'W':
442 brackets->ind_comp = TGSI_SWIZZLE_W;
443 break;
444 default:
445 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
446 return FALSE;
447 }
448 ctx->cur++;
449 eat_opt_white(&ctx->cur);
450 }
451
452 if (*ctx->cur == '+' || *ctx->cur == '-') {
453 boolean negate;
454
455 negate = *ctx->cur == '-';
456 ctx->cur++;
457 eat_opt_white( &ctx->cur );
458 if (!parse_uint( &ctx->cur, &uindex )) {
459 report_error( ctx, "Expected literal unsigned integer" );
460 return FALSE;
461 }
462 if (negate)
463 brackets->index = -(int) uindex;
464 else
465 brackets->index = (int) uindex;
466 }
467 else {
468 brackets->index = 0;
469 }
470 }
471 else {
472 if (!parse_uint( &ctx->cur, &uindex )) {
473 report_error( ctx, "Expected literal unsigned integer" );
474 return FALSE;
475 }
476 brackets->index = (int) uindex;
477 brackets->ind_file = TGSI_FILE_NULL;
478 brackets->ind_index = 0;
479 }
480 eat_opt_white( &ctx->cur );
481 if (*ctx->cur != ']') {
482 report_error( ctx, "Expected `]'" );
483 return FALSE;
484 }
485 ctx->cur++;
486 return TRUE;
487 }
488
489 static boolean
490 parse_opt_register_src_bracket(
491 struct translate_ctx *ctx,
492 struct parsed_bracket *brackets,
493 int *parsed_brackets)
494 {
495 const char *cur = ctx->cur;
496
497 *parsed_brackets = 0;
498
499 eat_opt_white( &cur );
500 if (cur[0] == '[') {
501 ++cur;
502 ctx->cur = cur;
503
504 if (!parse_register_bracket(ctx, brackets))
505 return FALSE;
506
507 *parsed_brackets = 1;
508 }
509
510 return TRUE;
511 }
512
513
514 /* Parse source register operand.
515 * <register_src> ::= <register_file_bracket_index> `]' |
516 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
517 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
518 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
519 */
520 static boolean
521 parse_register_src(
522 struct translate_ctx *ctx,
523 uint *file,
524 struct parsed_bracket *brackets)
525 {
526 brackets->ind_comp = TGSI_SWIZZLE_X;
527 if (!parse_register_file_bracket( ctx, file ))
528 return FALSE;
529 if (!parse_register_bracket( ctx, brackets ))
530 return FALSE;
531
532 return TRUE;
533 }
534
535 struct parsed_dcl_bracket {
536 uint first;
537 uint last;
538 };
539
540 static boolean
541 parse_register_dcl_bracket(
542 struct translate_ctx *ctx,
543 struct parsed_dcl_bracket *bracket)
544 {
545 uint uindex;
546 memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
547
548 eat_opt_white( &ctx->cur );
549
550 if (!parse_uint( &ctx->cur, &uindex )) {
551 /* it can be an empty bracket [] which means its range
552 * is from 0 to some implied size */
553 if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
554 bracket->first = 0;
555 bracket->last = ctx->implied_array_size - 1;
556 goto cleanup;
557 }
558 report_error( ctx, "Expected literal unsigned integer" );
559 return FALSE;
560 }
561 bracket->first = uindex;
562
563 eat_opt_white( &ctx->cur );
564
565 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
566 uint uindex;
567
568 ctx->cur += 2;
569 eat_opt_white( &ctx->cur );
570 if (!parse_uint( &ctx->cur, &uindex )) {
571 report_error( ctx, "Expected literal integer" );
572 return FALSE;
573 }
574 bracket->last = (int) uindex;
575 eat_opt_white( &ctx->cur );
576 }
577 else {
578 bracket->last = bracket->first;
579 }
580
581 cleanup:
582 if (*ctx->cur != ']') {
583 report_error( ctx, "Expected `]' or `..'" );
584 return FALSE;
585 }
586 ctx->cur++;
587 return TRUE;
588 }
589
590 /* Parse register declaration.
591 * <register_dcl> ::= <register_file_bracket_index> `]' |
592 * <register_file_bracket_index> `..' <index> `]'
593 */
594 static boolean
595 parse_register_dcl(
596 struct translate_ctx *ctx,
597 uint *file,
598 struct parsed_dcl_bracket *brackets,
599 int *num_brackets)
600 {
601 const char *cur;
602
603 *num_brackets = 0;
604
605 if (!parse_register_file_bracket( ctx, file ))
606 return FALSE;
607 if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
608 return FALSE;
609
610 *num_brackets = 1;
611
612 cur = ctx->cur;
613 eat_opt_white( &cur );
614
615 if (cur[0] == '[') {
616 ++cur;
617 ctx->cur = cur;
618 if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
619 return FALSE;
620 /* for geometry shader we don't really care about
621 * the first brackets it's always the size of the
622 * input primitive. so we want to declare just
623 * the index relevant to the semantics which is in
624 * the second bracket */
625 if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
626 brackets[0] = brackets[1];
627 *num_brackets = 1;
628 } else {
629 *num_brackets = 2;
630 }
631 }
632
633 return TRUE;
634 }
635
636
637 /* Parse destination register operand.*/
638 static boolean
639 parse_register_dst(
640 struct translate_ctx *ctx,
641 uint *file,
642 struct parsed_bracket *brackets)
643 {
644 brackets->ind_comp = TGSI_SWIZZLE_X;
645 if (!parse_register_file_bracket( ctx, file ))
646 return FALSE;
647 if (!parse_register_bracket( ctx, brackets ))
648 return FALSE;
649
650 return TRUE;
651 }
652
653 static boolean
654 parse_dst_operand(
655 struct translate_ctx *ctx,
656 struct tgsi_full_dst_register *dst )
657 {
658 uint file;
659 uint writemask;
660 const char *cur;
661 struct parsed_bracket bracket[2];
662 int parsed_opt_brackets;
663
664 if (!parse_register_dst( ctx, &file, &bracket[0] ))
665 return FALSE;
666 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
667 return FALSE;
668
669 cur = ctx->cur;
670 eat_opt_white( &cur );
671
672 if (!parse_opt_writemask( ctx, &writemask ))
673 return FALSE;
674
675 dst->Register.File = file;
676 if (parsed_opt_brackets) {
677 dst->Register.Dimension = 1;
678 dst->Dimension.Indirect = 0;
679 dst->Dimension.Dimension = 0;
680 dst->Dimension.Index = bracket[0].index;
681 bracket[0] = bracket[1];
682 }
683 dst->Register.Index = bracket[0].index;
684 dst->Register.WriteMask = writemask;
685 if (bracket[0].ind_file != TGSI_FILE_NULL) {
686 dst->Register.Indirect = 1;
687 dst->Indirect.File = bracket[0].ind_file;
688 dst->Indirect.Index = bracket[0].ind_index;
689 dst->Indirect.SwizzleX = bracket[0].ind_comp;
690 dst->Indirect.SwizzleY = bracket[0].ind_comp;
691 dst->Indirect.SwizzleZ = bracket[0].ind_comp;
692 dst->Indirect.SwizzleW = bracket[0].ind_comp;
693 }
694 return TRUE;
695 }
696
697 static boolean
698 parse_optional_swizzle(
699 struct translate_ctx *ctx,
700 uint swizzle[4],
701 boolean *parsed_swizzle )
702 {
703 const char *cur = ctx->cur;
704
705 *parsed_swizzle = FALSE;
706
707 eat_opt_white( &cur );
708 if (*cur == '.') {
709 uint i;
710
711 cur++;
712 eat_opt_white( &cur );
713 for (i = 0; i < 4; i++) {
714 if (uprcase( *cur ) == 'X')
715 swizzle[i] = TGSI_SWIZZLE_X;
716 else if (uprcase( *cur ) == 'Y')
717 swizzle[i] = TGSI_SWIZZLE_Y;
718 else if (uprcase( *cur ) == 'Z')
719 swizzle[i] = TGSI_SWIZZLE_Z;
720 else if (uprcase( *cur ) == 'W')
721 swizzle[i] = TGSI_SWIZZLE_W;
722 else {
723 report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
724 return FALSE;
725 }
726 cur++;
727 }
728 *parsed_swizzle = TRUE;
729 ctx->cur = cur;
730 }
731 return TRUE;
732 }
733
734 static boolean
735 parse_src_operand(
736 struct translate_ctx *ctx,
737 struct tgsi_full_src_register *src )
738 {
739 uint file;
740 uint swizzle[4];
741 boolean parsed_swizzle;
742 struct parsed_bracket bracket[2];
743 int parsed_opt_brackets;
744
745 if (*ctx->cur == '-') {
746 ctx->cur++;
747 eat_opt_white( &ctx->cur );
748 src->Register.Negate = 1;
749 }
750
751 if (*ctx->cur == '|') {
752 ctx->cur++;
753 eat_opt_white( &ctx->cur );
754 src->Register.Absolute = 1;
755 }
756
757 if (!parse_register_src(ctx, &file, &bracket[0]))
758 return FALSE;
759 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
760 return FALSE;
761
762 src->Register.File = file;
763 if (parsed_opt_brackets) {
764 src->Register.Dimension = 1;
765 src->Dimension.Indirect = 0;
766 src->Dimension.Dimension = 0;
767 src->Dimension.Index = bracket[0].index;
768 bracket[0] = bracket[1];
769 }
770 src->Register.Index = bracket[0].index;
771 if (bracket[0].ind_file != TGSI_FILE_NULL) {
772 src->Register.Indirect = 1;
773 src->Indirect.File = bracket[0].ind_file;
774 src->Indirect.Index = bracket[0].ind_index;
775 src->Indirect.SwizzleX = bracket[0].ind_comp;
776 src->Indirect.SwizzleY = bracket[0].ind_comp;
777 src->Indirect.SwizzleZ = bracket[0].ind_comp;
778 src->Indirect.SwizzleW = bracket[0].ind_comp;
779 }
780
781 /* Parse optional swizzle.
782 */
783 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
784 if (parsed_swizzle) {
785 src->Register.SwizzleX = swizzle[0];
786 src->Register.SwizzleY = swizzle[1];
787 src->Register.SwizzleZ = swizzle[2];
788 src->Register.SwizzleW = swizzle[3];
789 }
790 }
791
792 if (src->Register.Absolute) {
793 eat_opt_white( &ctx->cur );
794 if (*ctx->cur != '|') {
795 report_error( ctx, "Expected `|'" );
796 return FALSE;
797 }
798 ctx->cur++;
799 }
800
801
802 return TRUE;
803 }
804
805 static boolean
806 match_inst_mnemonic(const char **pcur,
807 const struct tgsi_opcode_info *info)
808 {
809 if (str_match_no_case(pcur, info->mnemonic)) {
810 return TRUE;
811 }
812 return FALSE;
813 }
814
815 static boolean
816 parse_instruction(
817 struct translate_ctx *ctx,
818 boolean has_label )
819 {
820 uint i;
821 uint saturate = TGSI_SAT_NONE;
822 const struct tgsi_opcode_info *info;
823 struct tgsi_full_instruction inst;
824 uint advance;
825
826 inst = tgsi_default_full_instruction();
827
828 /* Parse predicate.
829 */
830 eat_opt_white( &ctx->cur );
831 if (*ctx->cur == '(') {
832 uint file;
833 int index;
834 uint swizzle[4];
835 boolean parsed_swizzle;
836
837 inst.Instruction.Predicate = 1;
838
839 ctx->cur++;
840 if (*ctx->cur == '!') {
841 ctx->cur++;
842 inst.Predicate.Negate = 1;
843 }
844
845 if (!parse_register_1d( ctx, &file, &index ))
846 return FALSE;
847
848 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
849 if (parsed_swizzle) {
850 inst.Predicate.SwizzleX = swizzle[0];
851 inst.Predicate.SwizzleY = swizzle[1];
852 inst.Predicate.SwizzleZ = swizzle[2];
853 inst.Predicate.SwizzleW = swizzle[3];
854 }
855 }
856
857 if (*ctx->cur != ')') {
858 report_error( ctx, "Expected `)'" );
859 return FALSE;
860 }
861
862 ctx->cur++;
863 }
864
865 /* Parse instruction name.
866 */
867 eat_opt_white( &ctx->cur );
868 for (i = 0; i < TGSI_OPCODE_LAST; i++) {
869 const char *cur = ctx->cur;
870
871 info = tgsi_get_opcode_info( i );
872 if (match_inst_mnemonic(&cur, info)) {
873 if (str_match_no_case( &cur, "_SATNV" ))
874 saturate = TGSI_SAT_MINUS_PLUS_ONE;
875 else if (str_match_no_case( &cur, "_SAT" ))
876 saturate = TGSI_SAT_ZERO_ONE;
877
878 if (info->num_dst + info->num_src + info->is_tex == 0) {
879 if (!is_digit_alpha_underscore( cur )) {
880 ctx->cur = cur;
881 break;
882 }
883 }
884 else if (*cur == '\0' || eat_white( &cur )) {
885 ctx->cur = cur;
886 break;
887 }
888 }
889 }
890 if (i == TGSI_OPCODE_LAST) {
891 if (has_label)
892 report_error( ctx, "Unknown opcode" );
893 else
894 report_error( ctx, "Expected `DCL', `IMM' or a label" );
895 return FALSE;
896 }
897
898 inst.Instruction.Opcode = i;
899 inst.Instruction.Saturate = saturate;
900 inst.Instruction.NumDstRegs = info->num_dst;
901 inst.Instruction.NumSrcRegs = info->num_src;
902
903 /* Parse instruction operands.
904 */
905 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
906 if (i > 0) {
907 eat_opt_white( &ctx->cur );
908 if (*ctx->cur != ',') {
909 report_error( ctx, "Expected `,'" );
910 return FALSE;
911 }
912 ctx->cur++;
913 eat_opt_white( &ctx->cur );
914 }
915
916 if (i < info->num_dst) {
917 if (!parse_dst_operand( ctx, &inst.Dst[i] ))
918 return FALSE;
919 }
920 else if (i < info->num_dst + info->num_src) {
921 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
922 return FALSE;
923 }
924 else {
925 uint j;
926
927 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
928 if (str_match_no_case( &ctx->cur, tgsi_texture_names[j] )) {
929 if (!is_digit_alpha_underscore( ctx->cur )) {
930 inst.Instruction.Texture = 1;
931 inst.Texture.Texture = j;
932 break;
933 }
934 }
935 }
936 if (j == TGSI_TEXTURE_COUNT) {
937 report_error( ctx, "Expected texture target" );
938 return FALSE;
939 }
940 }
941 }
942
943 if (info->is_branch) {
944 uint target;
945
946 eat_opt_white( &ctx->cur );
947 if (*ctx->cur != ':') {
948 report_error( ctx, "Expected `:'" );
949 return FALSE;
950 }
951 ctx->cur++;
952 eat_opt_white( &ctx->cur );
953 if (!parse_uint( &ctx->cur, &target )) {
954 report_error( ctx, "Expected a label" );
955 return FALSE;
956 }
957 inst.Instruction.Label = 1;
958 inst.Label.Label = target;
959 }
960
961 advance = tgsi_build_full_instruction(
962 &inst,
963 ctx->tokens_cur,
964 ctx->header,
965 (uint) (ctx->tokens_end - ctx->tokens_cur) );
966 if (advance == 0)
967 return FALSE;
968 ctx->tokens_cur += advance;
969
970 return TRUE;
971 }
972
973 /* parses a 4-touple of the form {x, y, z, w}
974 * where x, y, z, w are numbers */
975 static boolean parse_immediate_data(struct translate_ctx *ctx,
976 float *values)
977 {
978 unsigned i;
979
980 eat_opt_white( &ctx->cur );
981 if (*ctx->cur != '{') {
982 report_error( ctx, "Expected `{'" );
983 return FALSE;
984 }
985 ctx->cur++;
986 for (i = 0; i < 4; i++) {
987 eat_opt_white( &ctx->cur );
988 if (i > 0) {
989 if (*ctx->cur != ',') {
990 report_error( ctx, "Expected `,'" );
991 return FALSE;
992 }
993 ctx->cur++;
994 eat_opt_white( &ctx->cur );
995 }
996 if (!parse_float( &ctx->cur, &values[i] )) {
997 report_error( ctx, "Expected literal floating point" );
998 return FALSE;
999 }
1000 }
1001 eat_opt_white( &ctx->cur );
1002 if (*ctx->cur != '}') {
1003 report_error( ctx, "Expected `}'" );
1004 return FALSE;
1005 }
1006 ctx->cur++;
1007
1008 return TRUE;
1009 }
1010
1011 static boolean parse_declaration( struct translate_ctx *ctx )
1012 {
1013 struct tgsi_full_declaration decl;
1014 uint file;
1015 struct parsed_dcl_bracket brackets[2];
1016 int num_brackets;
1017 uint writemask;
1018 const char *cur;
1019 uint advance;
1020 boolean is_vs_input;
1021 boolean is_imm_array;
1022
1023 if (!eat_white( &ctx->cur )) {
1024 report_error( ctx, "Syntax error" );
1025 return FALSE;
1026 }
1027 if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1028 return FALSE;
1029 if (!parse_opt_writemask( ctx, &writemask ))
1030 return FALSE;
1031
1032 decl = tgsi_default_full_declaration();
1033 decl.Declaration.File = file;
1034 decl.Declaration.UsageMask = writemask;
1035
1036 if (num_brackets == 1) {
1037 decl.Range.First = brackets[0].first;
1038 decl.Range.Last = brackets[0].last;
1039 } else {
1040 decl.Range.First = brackets[1].first;
1041 decl.Range.Last = brackets[1].last;
1042
1043 decl.Declaration.Dimension = 1;
1044 decl.Dim.Index2D = brackets[0].first;
1045 }
1046
1047 is_vs_input = (file == TGSI_FILE_INPUT &&
1048 ctx->processor == TGSI_PROCESSOR_VERTEX);
1049 is_imm_array = (file == TGSI_FILE_IMMEDIATE_ARRAY);
1050
1051 cur = ctx->cur;
1052 eat_opt_white( &cur );
1053 if (*cur == ',' && !is_vs_input) {
1054 uint i, j;
1055
1056 cur++;
1057 eat_opt_white( &cur );
1058 if (file == TGSI_FILE_RESOURCE) {
1059 for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1060 if (str_match_no_case(&cur, tgsi_texture_names[i])) {
1061 if (!is_digit_alpha_underscore(cur)) {
1062 decl.Resource.Resource = i;
1063 break;
1064 }
1065 }
1066 }
1067 if (i == TGSI_TEXTURE_COUNT) {
1068 report_error(ctx, "Expected texture target");
1069 return FALSE;
1070 }
1071
1072 ctx->cur = cur;
1073
1074 } else if (file == TGSI_FILE_SAMPLER_VIEW) {
1075 for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1076 if (str_match_no_case(&cur, tgsi_texture_names[i])) {
1077 if (!is_digit_alpha_underscore(cur)) {
1078 decl.SamplerView.Resource = i;
1079 break;
1080 }
1081 }
1082 }
1083 if (i == TGSI_TEXTURE_COUNT) {
1084 report_error(ctx, "Expected texture target");
1085 return FALSE;
1086 }
1087 eat_opt_white( &cur );
1088 if (*cur != ',') {
1089 report_error( ctx, "Expected `,'" );
1090 return FALSE;
1091 }
1092 ++cur;
1093 eat_opt_white( &cur );
1094 for (j = 0; j < 4; ++j) {
1095 for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
1096 if (str_match_no_case(&cur, tgsi_type_names[i])) {
1097 if (!is_digit_alpha_underscore(cur)) {
1098 switch (j) {
1099 case 0:
1100 decl.SamplerView.ReturnTypeX = i;
1101 break;
1102 case 1:
1103 decl.SamplerView.ReturnTypeY = i;
1104 break;
1105 case 2:
1106 decl.SamplerView.ReturnTypeZ = i;
1107 break;
1108 case 3:
1109 decl.SamplerView.ReturnTypeW = i;
1110 break;
1111 default:
1112 assert(0);
1113 }
1114 break;
1115 }
1116 }
1117 }
1118 if (i == PIPE_TYPE_COUNT) {
1119 if (j == 0 || j > 2) {
1120 report_error(ctx, "Expected type name");
1121 return FALSE;
1122 }
1123 break;
1124 } else {
1125 const char *cur2 = cur;
1126 eat_opt_white( &cur2 );
1127 if (*cur2 == ',') {
1128 cur2++;
1129 eat_opt_white( &cur2 );
1130 cur = cur2;
1131 continue;
1132 } else
1133 break;
1134 }
1135 }
1136 if (j < 4) {
1137 decl.SamplerView.ReturnTypeY =
1138 decl.SamplerView.ReturnTypeZ =
1139 decl.SamplerView.ReturnTypeW =
1140 decl.SamplerView.ReturnTypeX;
1141 }
1142 ctx->cur = cur;
1143 } else {
1144 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1145 if (str_match_no_case( &cur, tgsi_semantic_names[i] )) {
1146 const char *cur2 = cur;
1147 uint index;
1148
1149 if (is_digit_alpha_underscore( cur ))
1150 continue;
1151 eat_opt_white( &cur2 );
1152 if (*cur2 == '[') {
1153 cur2++;
1154 eat_opt_white( &cur2 );
1155 if (!parse_uint( &cur2, &index )) {
1156 report_error( ctx, "Expected literal integer" );
1157 return FALSE;
1158 }
1159 eat_opt_white( &cur2 );
1160 if (*cur2 != ']') {
1161 report_error( ctx, "Expected `]'" );
1162 return FALSE;
1163 }
1164 cur2++;
1165
1166 decl.Semantic.Index = index;
1167
1168 cur = cur2;
1169 }
1170
1171 decl.Declaration.Semantic = 1;
1172 decl.Semantic.Name = i;
1173
1174 ctx->cur = cur;
1175 break;
1176 }
1177 }
1178 }
1179 } else if (is_imm_array) {
1180 unsigned i;
1181 float *vals_itr;
1182 /* we have our immediate data */
1183 if (*cur != '{') {
1184 report_error( ctx, "Immediate array without data" );
1185 return FALSE;
1186 }
1187 ++cur;
1188 ctx->cur = cur;
1189
1190 decl.ImmediateData.u =
1191 MALLOC(sizeof(union tgsi_immediate_data) * 4 *
1192 (decl.Range.Last + 1));
1193 vals_itr = (float*)decl.ImmediateData.u;
1194 for (i = 0; i <= decl.Range.Last; ++i) {
1195 if (!parse_immediate_data(ctx, vals_itr)) {
1196 FREE(decl.ImmediateData.u);
1197 return FALSE;
1198 }
1199 vals_itr += 4;
1200 eat_opt_white( &ctx->cur );
1201 if (*ctx->cur != ',') {
1202 if (i != decl.Range.Last) {
1203 report_error( ctx, "Not enough data in immediate array!" );
1204 FREE(decl.ImmediateData.u);
1205 return FALSE;
1206 }
1207 } else
1208 ++ctx->cur;
1209 }
1210 eat_opt_white( &ctx->cur );
1211 if (*ctx->cur != '}') {
1212 FREE(decl.ImmediateData.u);
1213 report_error( ctx, "Immediate array data missing closing '}'" );
1214 return FALSE;
1215 }
1216 ++ctx->cur;
1217 }
1218
1219 cur = ctx->cur;
1220 eat_opt_white( &cur );
1221 if (*cur == ',' && !is_vs_input) {
1222 uint i;
1223
1224 cur++;
1225 eat_opt_white( &cur );
1226 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1227 if (str_match_no_case( &cur, tgsi_interpolate_names[i] )) {
1228 if (is_digit_alpha_underscore( cur ))
1229 continue;
1230 decl.Declaration.Interpolate = 1;
1231 decl.Interp.Interpolate = i;
1232
1233 ctx->cur = cur;
1234 break;
1235 }
1236 }
1237 if (i == TGSI_INTERPOLATE_COUNT) {
1238 report_error( ctx, "Expected semantic or interpolate attribute" );
1239 return FALSE;
1240 }
1241 }
1242
1243 advance = tgsi_build_full_declaration(
1244 &decl,
1245 ctx->tokens_cur,
1246 ctx->header,
1247 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1248
1249 if (is_imm_array)
1250 FREE(decl.ImmediateData.u);
1251
1252 if (advance == 0)
1253 return FALSE;
1254 ctx->tokens_cur += advance;
1255
1256 return TRUE;
1257 }
1258
1259 static boolean parse_immediate( struct translate_ctx *ctx )
1260 {
1261 struct tgsi_full_immediate imm;
1262 float values[4];
1263 uint advance;
1264
1265 if (!eat_white( &ctx->cur )) {
1266 report_error( ctx, "Syntax error" );
1267 return FALSE;
1268 }
1269 if (!str_match_no_case( &ctx->cur, "FLT32" ) ||
1270 is_digit_alpha_underscore( ctx->cur )) {
1271 report_error( ctx, "Expected `FLT32'" );
1272 return FALSE;
1273 }
1274
1275 parse_immediate_data(ctx, values);
1276
1277 imm = tgsi_default_full_immediate();
1278 imm.Immediate.NrTokens += 4;
1279 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
1280 imm.u[0].Float = values[0];
1281 imm.u[1].Float = values[1];
1282 imm.u[2].Float = values[2];
1283 imm.u[3].Float = values[3];
1284
1285 advance = tgsi_build_full_immediate(
1286 &imm,
1287 ctx->tokens_cur,
1288 ctx->header,
1289 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1290 if (advance == 0)
1291 return FALSE;
1292 ctx->tokens_cur += advance;
1293
1294 return TRUE;
1295 }
1296
1297 static boolean
1298 parse_primitive( const char **pcur, uint *primitive )
1299 {
1300 uint i;
1301
1302 for (i = 0; i < PIPE_PRIM_MAX; i++) {
1303 const char *cur = *pcur;
1304
1305 if (str_match_no_case( &cur, tgsi_primitive_names[i])) {
1306 *primitive = i;
1307 *pcur = cur;
1308 return TRUE;
1309 }
1310 }
1311 return FALSE;
1312 }
1313
1314 static boolean
1315 parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1316 {
1317 uint i;
1318
1319 for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
1320 const char *cur = *pcur;
1321
1322 if (str_match_no_case( &cur, tgsi_fs_coord_origin_names[i])) {
1323 *fs_coord_origin = i;
1324 *pcur = cur;
1325 return TRUE;
1326 }
1327 }
1328 return FALSE;
1329 }
1330
1331 static boolean
1332 parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1333 {
1334 uint i;
1335
1336 for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
1337 const char *cur = *pcur;
1338
1339 if (str_match_no_case( &cur, tgsi_fs_coord_pixel_center_names[i])) {
1340 *fs_coord_pixel_center = i;
1341 *pcur = cur;
1342 return TRUE;
1343 }
1344 }
1345 return FALSE;
1346 }
1347
1348
1349 static boolean parse_property( struct translate_ctx *ctx )
1350 {
1351 struct tgsi_full_property prop;
1352 uint property_name;
1353 uint values[8];
1354 uint advance;
1355 char id[64];
1356
1357 if (!eat_white( &ctx->cur )) {
1358 report_error( ctx, "Syntax error" );
1359 return FALSE;
1360 }
1361 if (!parse_identifier( &ctx->cur, id )) {
1362 report_error( ctx, "Syntax error" );
1363 return FALSE;
1364 }
1365 for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1366 ++property_name) {
1367 if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
1368 break;
1369 }
1370 }
1371 if (property_name >= TGSI_PROPERTY_COUNT) {
1372 debug_printf( "\nError: Unknown property : '%s'", id );
1373 return FALSE;
1374 }
1375
1376 eat_opt_white( &ctx->cur );
1377 switch(property_name) {
1378 case TGSI_PROPERTY_GS_INPUT_PRIM:
1379 case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1380 if (!parse_primitive(&ctx->cur, &values[0] )) {
1381 report_error( ctx, "Unknown primitive name as property!" );
1382 return FALSE;
1383 }
1384 if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1385 ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
1386 ctx->implied_array_size = u_vertices_per_prim(values[0]);
1387 }
1388 break;
1389 case TGSI_PROPERTY_FS_COORD_ORIGIN:
1390 if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1391 report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1392 return FALSE;
1393 }
1394 break;
1395 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1396 if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1397 report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1398 return FALSE;
1399 }
1400 break;
1401 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
1402 default:
1403 if (!parse_uint(&ctx->cur, &values[0] )) {
1404 report_error( ctx, "Expected unsigned integer as property!" );
1405 return FALSE;
1406 }
1407 }
1408
1409 prop = tgsi_default_full_property();
1410 prop.Property.PropertyName = property_name;
1411 prop.Property.NrTokens += 1;
1412 prop.u[0].Data = values[0];
1413
1414 advance = tgsi_build_full_property(
1415 &prop,
1416 ctx->tokens_cur,
1417 ctx->header,
1418 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1419 if (advance == 0)
1420 return FALSE;
1421 ctx->tokens_cur += advance;
1422
1423 return TRUE;
1424 }
1425
1426
1427 static boolean translate( struct translate_ctx *ctx )
1428 {
1429 eat_opt_white( &ctx->cur );
1430 if (!parse_header( ctx ))
1431 return FALSE;
1432
1433 while (*ctx->cur != '\0') {
1434 uint label_val = 0;
1435 if (!eat_white( &ctx->cur )) {
1436 report_error( ctx, "Syntax error" );
1437 return FALSE;
1438 }
1439
1440 if (*ctx->cur == '\0')
1441 break;
1442 if (parse_label( ctx, &label_val )) {
1443 if (!parse_instruction( ctx, TRUE ))
1444 return FALSE;
1445 }
1446 else if (str_match_no_case( &ctx->cur, "DCL" )) {
1447 if (!parse_declaration( ctx ))
1448 return FALSE;
1449 }
1450 else if (str_match_no_case( &ctx->cur, "IMM" )) {
1451 if (!parse_immediate( ctx ))
1452 return FALSE;
1453 }
1454 else if (str_match_no_case( &ctx->cur, "PROPERTY" )) {
1455 if (!parse_property( ctx ))
1456 return FALSE;
1457 }
1458 else if (!parse_instruction( ctx, FALSE )) {
1459 return FALSE;
1460 }
1461 }
1462
1463 return TRUE;
1464 }
1465
1466 boolean
1467 tgsi_text_translate(
1468 const char *text,
1469 struct tgsi_token *tokens,
1470 uint num_tokens )
1471 {
1472 struct translate_ctx ctx;
1473
1474 ctx.text = text;
1475 ctx.cur = text;
1476 ctx.tokens = tokens;
1477 ctx.tokens_cur = tokens;
1478 ctx.tokens_end = tokens + num_tokens;
1479
1480 if (!translate( &ctx ))
1481 return FALSE;
1482
1483 return tgsi_sanity_check( tokens );
1484 }