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