revert 213 commits (to 56092) from the last month. 10 still need work to resolve...
[AROS.git] / workbench / libs / mesa / src / gallium / auxiliary / tgsi / tgsi_text.c
blob57622a0dea6339fe4552fb6b5df841a9890d7fb8
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:
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.
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.
26 **************************************************************************/
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"
41 static boolean is_alpha_underscore( const char *cur )
43 return
44 (*cur >= 'a' && *cur <= 'z') ||
45 (*cur >= 'A' && *cur <= 'Z') ||
46 *cur == '_';
49 static boolean is_digit( const char *cur )
51 return *cur >= '0' && *cur <= '9';
54 static boolean is_digit_alpha_underscore( const char *cur )
56 return is_digit( cur ) || is_alpha_underscore( cur );
59 static char uprcase( char c )
61 if (c >= 'a' && c <= 'z')
62 return c + 'A' - 'a';
63 return c;
67 * Ignore case of str1 and assume str1 is already uppercase.
68 * Return TRUE iff str1 and str2 are equal.
70 static int
71 streq_nocase_uprcase(const char *str1,
72 const char *str2)
74 while (*str1 && *str2) {
75 if (*str1 != uprcase(*str2))
76 return FALSE;
77 str1++;
78 str2++;
80 return *str1 == 0 && *str2 == 0;
83 static boolean str_match_no_case( const char **pcur, const char *str )
85 const char *cur = *pcur;
87 while (*str != '\0' && *str == uprcase( *cur )) {
88 str++;
89 cur++;
91 if (*str == '\0') {
92 *pcur = cur;
93 return TRUE;
95 return FALSE;
98 /* Eat zero or more whitespaces.
100 static void eat_opt_white( const char **pcur )
102 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
103 (*pcur)++;
106 /* Eat one or more whitespaces.
107 * Return TRUE if at least one whitespace eaten.
109 static boolean eat_white( const char **pcur )
111 const char *cur = *pcur;
113 eat_opt_white( pcur );
114 return *pcur > cur;
117 /* Parse unsigned integer.
118 * No checks for overflow.
120 static boolean parse_uint( const char **pcur, uint *val )
122 const char *cur = *pcur;
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;
131 return FALSE;
134 static boolean parse_identifier( const char **pcur, char *ret )
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 ) || is_digit( cur ))
141 ret[i++] = *cur++;
142 ret[i++] = '\0';
143 *pcur = cur;
144 return TRUE;
146 return FALSE;
149 /* Parse floating point.
151 static boolean parse_float( const char **pcur, float *val )
153 const char *cur = *pcur;
154 boolean integral_part = FALSE;
155 boolean fractional_part = FALSE;
157 *val = (float) atof( cur );
159 if (*cur == '-' || *cur == '+')
160 cur++;
161 if (is_digit( cur )) {
162 cur++;
163 integral_part = TRUE;
164 while (is_digit( cur ))
165 cur++;
167 if (*cur == '.') {
168 cur++;
169 if (is_digit( cur )) {
170 cur++;
171 fractional_part = TRUE;
172 while (is_digit( cur ))
173 cur++;
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++;
187 else
188 return FALSE;
190 *pcur = cur;
191 return TRUE;
194 struct translate_ctx
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;
206 static void report_error( struct translate_ctx *ctx, const char *msg )
208 int line = 1;
209 int column = 1;
210 const char *itr = ctx->text;
212 while (itr != ctx->cur) {
213 if (*itr == '\n') {
214 column = 1;
215 ++line;
217 ++column;
218 ++itr;
221 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
224 /* Parse shader header.
225 * Return TRUE for one of the following headers.
226 * FRAG
227 * GEOM
228 * VERT
230 static boolean parse_header( struct translate_ctx *ctx )
232 uint processor;
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;
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();
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;
255 return TRUE;
258 static boolean parse_label( struct translate_ctx *ctx, uint *val )
260 const char *cur = ctx->cur;
262 if (parse_uint( &cur, val )) {
263 eat_opt_white( &cur );
264 if (*cur == ':') {
265 cur++;
266 ctx->cur = cur;
267 return TRUE;
270 return FALSE;
273 static const char *file_names[TGSI_FILE_COUNT] =
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 "RES"
290 static boolean
291 parse_file( const char **pcur, uint *file )
293 uint i;
295 for (i = 0; i < TGSI_FILE_COUNT; i++) {
296 const char *cur = *pcur;
298 if (str_match_no_case( &cur, file_names[i] )) {
299 if (!is_digit_alpha_underscore( cur )) {
300 *pcur = cur;
301 *file = i;
302 return TRUE;
306 return FALSE;
309 static boolean
310 parse_opt_writemask(
311 struct translate_ctx *ctx,
312 uint *writemask )
314 const char *cur;
316 cur = ctx->cur;
317 eat_opt_white( &cur );
318 if (*cur == '.') {
319 cur++;
320 *writemask = TGSI_WRITEMASK_NONE;
321 eat_opt_white( &cur );
322 if (uprcase( *cur ) == 'X') {
323 cur++;
324 *writemask |= TGSI_WRITEMASK_X;
326 if (uprcase( *cur ) == 'Y') {
327 cur++;
328 *writemask |= TGSI_WRITEMASK_Y;
330 if (uprcase( *cur ) == 'Z') {
331 cur++;
332 *writemask |= TGSI_WRITEMASK_Z;
334 if (uprcase( *cur ) == 'W') {
335 cur++;
336 *writemask |= TGSI_WRITEMASK_W;
339 if (*writemask == TGSI_WRITEMASK_NONE) {
340 report_error( ctx, "Writemask expected" );
341 return FALSE;
344 ctx->cur = cur;
346 else {
347 *writemask = TGSI_WRITEMASK_XYZW;
349 return TRUE;
353 /* <register_file_bracket> ::= <file> `['
355 static boolean
356 parse_register_file_bracket(
357 struct translate_ctx *ctx,
358 uint *file )
360 if (!parse_file( &ctx->cur, file )) {
361 report_error( ctx, "Unknown register file" );
362 return FALSE;
364 eat_opt_white( &ctx->cur );
365 if (*ctx->cur != '[') {
366 report_error( ctx, "Expected `['" );
367 return FALSE;
369 ctx->cur++;
370 return TRUE;
373 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
375 static boolean
376 parse_register_file_bracket_index(
377 struct translate_ctx *ctx,
378 uint *file,
379 int *index )
381 uint uindex;
383 if (!parse_register_file_bracket( ctx, file ))
384 return FALSE;
385 eat_opt_white( &ctx->cur );
386 if (!parse_uint( &ctx->cur, &uindex )) {
387 report_error( ctx, "Expected literal unsigned integer" );
388 return FALSE;
390 *index = (int) uindex;
391 return TRUE;
394 /* Parse simple 1d register operand.
395 * <register_dst> ::= <register_file_bracket_index> `]'
397 static boolean
398 parse_register_1d(struct translate_ctx *ctx,
399 uint *file,
400 int *index )
402 if (!parse_register_file_bracket_index( ctx, file, index ))
403 return FALSE;
404 eat_opt_white( &ctx->cur );
405 if (*ctx->cur != ']') {
406 report_error( ctx, "Expected `]'" );
407 return FALSE;
409 ctx->cur++;
410 return TRUE;
413 struct parsed_bracket {
414 int index;
416 uint ind_file;
417 int ind_index;
418 uint ind_comp;
422 static boolean
423 parse_register_bracket(
424 struct translate_ctx *ctx,
425 struct parsed_bracket *brackets)
427 const char *cur;
428 uint uindex;
430 memset(brackets, 0, sizeof(struct parsed_bracket));
432 eat_opt_white( &ctx->cur );
434 cur = ctx->cur;
435 if (parse_file( &cur, &brackets->ind_file )) {
436 if (!parse_register_1d( ctx, &brackets->ind_file,
437 &brackets->ind_index ))
438 return FALSE;
439 eat_opt_white( &ctx->cur );
441 if (*ctx->cur == '.') {
442 ctx->cur++;
443 eat_opt_white(&ctx->cur);
445 switch (uprcase(*ctx->cur)) {
446 case 'X':
447 brackets->ind_comp = TGSI_SWIZZLE_X;
448 break;
449 case 'Y':
450 brackets->ind_comp = TGSI_SWIZZLE_Y;
451 break;
452 case 'Z':
453 brackets->ind_comp = TGSI_SWIZZLE_Z;
454 break;
455 case 'W':
456 brackets->ind_comp = TGSI_SWIZZLE_W;
457 break;
458 default:
459 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
460 return FALSE;
462 ctx->cur++;
463 eat_opt_white(&ctx->cur);
466 if (*ctx->cur == '+' || *ctx->cur == '-') {
467 boolean negate;
469 negate = *ctx->cur == '-';
470 ctx->cur++;
471 eat_opt_white( &ctx->cur );
472 if (!parse_uint( &ctx->cur, &uindex )) {
473 report_error( ctx, "Expected literal unsigned integer" );
474 return FALSE;
476 if (negate)
477 brackets->index = -(int) uindex;
478 else
479 brackets->index = (int) uindex;
481 else {
482 brackets->index = 0;
485 else {
486 if (!parse_uint( &ctx->cur, &uindex )) {
487 report_error( ctx, "Expected literal unsigned integer" );
488 return FALSE;
490 brackets->index = (int) uindex;
491 brackets->ind_file = TGSI_FILE_NULL;
492 brackets->ind_index = 0;
494 eat_opt_white( &ctx->cur );
495 if (*ctx->cur != ']') {
496 report_error( ctx, "Expected `]'" );
497 return FALSE;
499 ctx->cur++;
500 return TRUE;
503 static boolean
504 parse_opt_register_src_bracket(
505 struct translate_ctx *ctx,
506 struct parsed_bracket *brackets,
507 int *parsed_brackets)
509 const char *cur = ctx->cur;
511 *parsed_brackets = 0;
513 eat_opt_white( &cur );
514 if (cur[0] == '[') {
515 ++cur;
516 ctx->cur = cur;
518 if (!parse_register_bracket(ctx, brackets))
519 return FALSE;
521 *parsed_brackets = 1;
524 return TRUE;
528 /* Parse source register operand.
529 * <register_src> ::= <register_file_bracket_index> `]' |
530 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
531 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
532 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
534 static boolean
535 parse_register_src(
536 struct translate_ctx *ctx,
537 uint *file,
538 struct parsed_bracket *brackets)
540 brackets->ind_comp = TGSI_SWIZZLE_X;
541 if (!parse_register_file_bracket( ctx, file ))
542 return FALSE;
543 if (!parse_register_bracket( ctx, brackets ))
544 return FALSE;
546 return TRUE;
549 struct parsed_dcl_bracket {
550 uint first;
551 uint last;
554 static boolean
555 parse_register_dcl_bracket(
556 struct translate_ctx *ctx,
557 struct parsed_dcl_bracket *bracket)
559 uint uindex;
560 memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
562 eat_opt_white( &ctx->cur );
564 if (!parse_uint( &ctx->cur, &uindex )) {
565 /* it can be an empty bracket [] which means its range
566 * is from 0 to some implied size */
567 if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
568 bracket->first = 0;
569 bracket->last = ctx->implied_array_size - 1;
570 goto cleanup;
572 report_error( ctx, "Expected literal unsigned integer" );
573 return FALSE;
575 bracket->first = uindex;
577 eat_opt_white( &ctx->cur );
579 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
580 uint uindex;
582 ctx->cur += 2;
583 eat_opt_white( &ctx->cur );
584 if (!parse_uint( &ctx->cur, &uindex )) {
585 report_error( ctx, "Expected literal integer" );
586 return FALSE;
588 bracket->last = (int) uindex;
589 eat_opt_white( &ctx->cur );
591 else {
592 bracket->last = bracket->first;
595 cleanup:
596 if (*ctx->cur != ']') {
597 report_error( ctx, "Expected `]' or `..'" );
598 return FALSE;
600 ctx->cur++;
601 return TRUE;
604 /* Parse register declaration.
605 * <register_dcl> ::= <register_file_bracket_index> `]' |
606 * <register_file_bracket_index> `..' <index> `]'
608 static boolean
609 parse_register_dcl(
610 struct translate_ctx *ctx,
611 uint *file,
612 struct parsed_dcl_bracket *brackets,
613 int *num_brackets)
615 const char *cur;
617 *num_brackets = 0;
619 if (!parse_register_file_bracket( ctx, file ))
620 return FALSE;
621 if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
622 return FALSE;
624 *num_brackets = 1;
626 cur = ctx->cur;
627 eat_opt_white( &cur );
629 if (cur[0] == '[') {
630 ++cur;
631 ctx->cur = cur;
632 if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
633 return FALSE;
634 /* for geometry shader we don't really care about
635 * the first brackets it's always the size of the
636 * input primitive. so we want to declare just
637 * the index relevant to the semantics which is in
638 * the second bracket */
639 if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
640 brackets[0] = brackets[1];
641 *num_brackets = 1;
642 } else {
643 *num_brackets = 2;
647 return TRUE;
651 /* Parse destination register operand.*/
652 static boolean
653 parse_register_dst(
654 struct translate_ctx *ctx,
655 uint *file,
656 struct parsed_bracket *brackets)
658 brackets->ind_comp = TGSI_SWIZZLE_X;
659 if (!parse_register_file_bracket( ctx, file ))
660 return FALSE;
661 if (!parse_register_bracket( ctx, brackets ))
662 return FALSE;
664 return TRUE;
667 static boolean
668 parse_dst_operand(
669 struct translate_ctx *ctx,
670 struct tgsi_full_dst_register *dst )
672 uint file;
673 uint writemask;
674 const char *cur;
675 struct parsed_bracket bracket[2];
676 int parsed_opt_brackets;
678 if (!parse_register_dst( ctx, &file, &bracket[0] ))
679 return FALSE;
680 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
681 return FALSE;
683 cur = ctx->cur;
684 eat_opt_white( &cur );
686 if (!parse_opt_writemask( ctx, &writemask ))
687 return FALSE;
689 dst->Register.File = file;
690 if (parsed_opt_brackets) {
691 dst->Register.Dimension = 1;
692 dst->Dimension.Indirect = 0;
693 dst->Dimension.Dimension = 0;
694 dst->Dimension.Index = bracket[0].index;
695 bracket[0] = bracket[1];
697 dst->Register.Index = bracket[0].index;
698 dst->Register.WriteMask = writemask;
699 if (bracket[0].ind_file != TGSI_FILE_NULL) {
700 dst->Register.Indirect = 1;
701 dst->Indirect.File = bracket[0].ind_file;
702 dst->Indirect.Index = bracket[0].ind_index;
703 dst->Indirect.SwizzleX = bracket[0].ind_comp;
704 dst->Indirect.SwizzleY = bracket[0].ind_comp;
705 dst->Indirect.SwizzleZ = bracket[0].ind_comp;
706 dst->Indirect.SwizzleW = bracket[0].ind_comp;
708 return TRUE;
711 static boolean
712 parse_optional_swizzle(
713 struct translate_ctx *ctx,
714 uint swizzle[4],
715 boolean *parsed_swizzle )
717 const char *cur = ctx->cur;
719 *parsed_swizzle = FALSE;
721 eat_opt_white( &cur );
722 if (*cur == '.') {
723 uint i;
725 cur++;
726 eat_opt_white( &cur );
727 for (i = 0; i < 4; i++) {
728 if (uprcase( *cur ) == 'X')
729 swizzle[i] = TGSI_SWIZZLE_X;
730 else if (uprcase( *cur ) == 'Y')
731 swizzle[i] = TGSI_SWIZZLE_Y;
732 else if (uprcase( *cur ) == 'Z')
733 swizzle[i] = TGSI_SWIZZLE_Z;
734 else if (uprcase( *cur ) == 'W')
735 swizzle[i] = TGSI_SWIZZLE_W;
736 else {
737 report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
738 return FALSE;
740 cur++;
742 *parsed_swizzle = TRUE;
743 ctx->cur = cur;
745 return TRUE;
748 static boolean
749 parse_src_operand(
750 struct translate_ctx *ctx,
751 struct tgsi_full_src_register *src )
753 uint file;
754 uint swizzle[4];
755 boolean parsed_swizzle;
756 struct parsed_bracket bracket[2];
757 int parsed_opt_brackets;
759 if (*ctx->cur == '-') {
760 ctx->cur++;
761 eat_opt_white( &ctx->cur );
762 src->Register.Negate = 1;
765 if (*ctx->cur == '|') {
766 ctx->cur++;
767 eat_opt_white( &ctx->cur );
768 src->Register.Absolute = 1;
771 if (!parse_register_src(ctx, &file, &bracket[0]))
772 return FALSE;
773 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
774 return FALSE;
776 src->Register.File = file;
777 if (parsed_opt_brackets) {
778 src->Register.Dimension = 1;
779 src->Dimension.Indirect = 0;
780 src->Dimension.Dimension = 0;
781 src->Dimension.Index = bracket[0].index;
782 bracket[0] = bracket[1];
784 src->Register.Index = bracket[0].index;
785 if (bracket[0].ind_file != TGSI_FILE_NULL) {
786 src->Register.Indirect = 1;
787 src->Indirect.File = bracket[0].ind_file;
788 src->Indirect.Index = bracket[0].ind_index;
789 src->Indirect.SwizzleX = bracket[0].ind_comp;
790 src->Indirect.SwizzleY = bracket[0].ind_comp;
791 src->Indirect.SwizzleZ = bracket[0].ind_comp;
792 src->Indirect.SwizzleW = bracket[0].ind_comp;
795 /* Parse optional swizzle.
797 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
798 if (parsed_swizzle) {
799 src->Register.SwizzleX = swizzle[0];
800 src->Register.SwizzleY = swizzle[1];
801 src->Register.SwizzleZ = swizzle[2];
802 src->Register.SwizzleW = swizzle[3];
806 if (src->Register.Absolute) {
807 eat_opt_white( &ctx->cur );
808 if (*ctx->cur != '|') {
809 report_error( ctx, "Expected `|'" );
810 return FALSE;
812 ctx->cur++;
816 return TRUE;
819 static const char *texture_names[TGSI_TEXTURE_COUNT] =
821 "UNKNOWN",
822 "1D",
823 "2D",
824 "3D",
825 "CUBE",
826 "RECT",
827 "SHADOW1D",
828 "SHADOW2D",
829 "SHADOWRECT"
832 static const char *type_names[] =
834 "UNORM",
835 "SNORM",
836 "SINT",
837 "UINT",
838 "FLOAT"
841 static boolean
842 match_inst_mnemonic(const char **pcur,
843 const struct tgsi_opcode_info *info)
845 if (str_match_no_case(pcur, info->mnemonic)) {
846 return TRUE;
848 return FALSE;
851 static boolean
852 parse_instruction(
853 struct translate_ctx *ctx,
854 boolean has_label )
856 uint i;
857 uint saturate = TGSI_SAT_NONE;
858 const struct tgsi_opcode_info *info;
859 struct tgsi_full_instruction inst;
860 uint advance;
862 inst = tgsi_default_full_instruction();
864 /* Parse predicate.
866 eat_opt_white( &ctx->cur );
867 if (*ctx->cur == '(') {
868 uint file;
869 int index;
870 uint swizzle[4];
871 boolean parsed_swizzle;
873 inst.Instruction.Predicate = 1;
875 ctx->cur++;
876 if (*ctx->cur == '!') {
877 ctx->cur++;
878 inst.Predicate.Negate = 1;
881 if (!parse_register_1d( ctx, &file, &index ))
882 return FALSE;
884 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
885 if (parsed_swizzle) {
886 inst.Predicate.SwizzleX = swizzle[0];
887 inst.Predicate.SwizzleY = swizzle[1];
888 inst.Predicate.SwizzleZ = swizzle[2];
889 inst.Predicate.SwizzleW = swizzle[3];
893 if (*ctx->cur != ')') {
894 report_error( ctx, "Expected `)'" );
895 return FALSE;
898 ctx->cur++;
901 /* Parse instruction name.
903 eat_opt_white( &ctx->cur );
904 for (i = 0; i < TGSI_OPCODE_LAST; i++) {
905 const char *cur = ctx->cur;
907 info = tgsi_get_opcode_info( i );
908 if (match_inst_mnemonic(&cur, info)) {
909 if (str_match_no_case( &cur, "_SATNV" ))
910 saturate = TGSI_SAT_MINUS_PLUS_ONE;
911 else if (str_match_no_case( &cur, "_SAT" ))
912 saturate = TGSI_SAT_ZERO_ONE;
914 if (info->num_dst + info->num_src + info->is_tex == 0) {
915 if (!is_digit_alpha_underscore( cur )) {
916 ctx->cur = cur;
917 break;
920 else if (*cur == '\0' || eat_white( &cur )) {
921 ctx->cur = cur;
922 break;
926 if (i == TGSI_OPCODE_LAST) {
927 if (has_label)
928 report_error( ctx, "Unknown opcode" );
929 else
930 report_error( ctx, "Expected `DCL', `IMM' or a label" );
931 return FALSE;
934 inst.Instruction.Opcode = i;
935 inst.Instruction.Saturate = saturate;
936 inst.Instruction.NumDstRegs = info->num_dst;
937 inst.Instruction.NumSrcRegs = info->num_src;
939 /* Parse instruction operands.
941 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
942 if (i > 0) {
943 eat_opt_white( &ctx->cur );
944 if (*ctx->cur != ',') {
945 report_error( ctx, "Expected `,'" );
946 return FALSE;
948 ctx->cur++;
949 eat_opt_white( &ctx->cur );
952 if (i < info->num_dst) {
953 if (!parse_dst_operand( ctx, &inst.Dst[i] ))
954 return FALSE;
956 else if (i < info->num_dst + info->num_src) {
957 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
958 return FALSE;
960 else {
961 uint j;
963 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
964 if (str_match_no_case( &ctx->cur, texture_names[j] )) {
965 if (!is_digit_alpha_underscore( ctx->cur )) {
966 inst.Instruction.Texture = 1;
967 inst.Texture.Texture = j;
968 break;
972 if (j == TGSI_TEXTURE_COUNT) {
973 report_error( ctx, "Expected texture target" );
974 return FALSE;
979 if (info->is_branch) {
980 uint target;
982 eat_opt_white( &ctx->cur );
983 if (*ctx->cur != ':') {
984 report_error( ctx, "Expected `:'" );
985 return FALSE;
987 ctx->cur++;
988 eat_opt_white( &ctx->cur );
989 if (!parse_uint( &ctx->cur, &target )) {
990 report_error( ctx, "Expected a label" );
991 return FALSE;
993 inst.Instruction.Label = 1;
994 inst.Label.Label = target;
997 advance = tgsi_build_full_instruction(
998 &inst,
999 ctx->tokens_cur,
1000 ctx->header,
1001 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1002 if (advance == 0)
1003 return FALSE;
1004 ctx->tokens_cur += advance;
1006 return TRUE;
1009 static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
1011 "POSITION",
1012 "COLOR",
1013 "BCOLOR",
1014 "FOG",
1015 "PSIZE",
1016 "GENERIC",
1017 "NORMAL",
1018 "FACE",
1019 "EDGEFLAG",
1020 "PRIM_ID",
1021 "INSTANCEID",
1022 "STENCIL"
1025 static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
1027 "CONSTANT",
1028 "LINEAR",
1029 "PERSPECTIVE"
1033 /* parses a 4-touple of the form {x, y, z, w}
1034 * where x, y, z, w are numbers */
1035 static boolean parse_immediate_data(struct translate_ctx *ctx,
1036 float *values)
1038 unsigned i;
1040 eat_opt_white( &ctx->cur );
1041 if (*ctx->cur != '{') {
1042 report_error( ctx, "Expected `{'" );
1043 return FALSE;
1045 ctx->cur++;
1046 for (i = 0; i < 4; i++) {
1047 eat_opt_white( &ctx->cur );
1048 if (i > 0) {
1049 if (*ctx->cur != ',') {
1050 report_error( ctx, "Expected `,'" );
1051 return FALSE;
1053 ctx->cur++;
1054 eat_opt_white( &ctx->cur );
1056 if (!parse_float( &ctx->cur, &values[i] )) {
1057 report_error( ctx, "Expected literal floating point" );
1058 return FALSE;
1061 eat_opt_white( &ctx->cur );
1062 if (*ctx->cur != '}') {
1063 report_error( ctx, "Expected `}'" );
1064 return FALSE;
1066 ctx->cur++;
1068 return TRUE;
1071 static boolean parse_declaration( struct translate_ctx *ctx )
1073 struct tgsi_full_declaration decl;
1074 uint file;
1075 struct parsed_dcl_bracket brackets[2];
1076 int num_brackets;
1077 uint writemask;
1078 const char *cur;
1079 uint advance;
1080 boolean is_vs_input;
1081 boolean is_imm_array;
1083 assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT);
1084 assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT);
1086 if (!eat_white( &ctx->cur )) {
1087 report_error( ctx, "Syntax error" );
1088 return FALSE;
1090 if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1091 return FALSE;
1092 if (!parse_opt_writemask( ctx, &writemask ))
1093 return FALSE;
1095 decl = tgsi_default_full_declaration();
1096 decl.Declaration.File = file;
1097 decl.Declaration.UsageMask = writemask;
1099 if (num_brackets == 1) {
1100 decl.Range.First = brackets[0].first;
1101 decl.Range.Last = brackets[0].last;
1102 } else {
1103 decl.Range.First = brackets[1].first;
1104 decl.Range.Last = brackets[1].last;
1106 decl.Declaration.Dimension = 1;
1107 decl.Dim.Index2D = brackets[0].first;
1110 is_vs_input = (file == TGSI_FILE_INPUT &&
1111 ctx->processor == TGSI_PROCESSOR_VERTEX);
1112 is_imm_array = (file == TGSI_FILE_IMMEDIATE_ARRAY);
1114 cur = ctx->cur;
1115 eat_opt_white( &cur );
1116 if (*cur == ',' && !is_vs_input) {
1117 uint i, j;
1119 cur++;
1120 eat_opt_white( &cur );
1121 if (file == TGSI_FILE_RESOURCE) {
1122 for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1123 if (str_match_no_case(&cur, texture_names[i])) {
1124 if (!is_digit_alpha_underscore(cur)) {
1125 decl.Resource.Resource = i;
1126 break;
1130 if (i == TGSI_TEXTURE_COUNT) {
1131 report_error(ctx, "Expected texture target");
1132 return FALSE;
1134 eat_opt_white( &cur );
1135 if (*cur != ',') {
1136 report_error( ctx, "Expected `,'" );
1137 return FALSE;
1139 ++cur;
1140 eat_opt_white( &cur );
1141 for (j = 0; j < 4; ++j) {
1142 for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
1143 if (str_match_no_case(&cur, type_names[i])) {
1144 if (!is_digit_alpha_underscore(cur)) {
1145 switch (j) {
1146 case 0:
1147 decl.Resource.ReturnTypeX = i;
1148 break;
1149 case 1:
1150 decl.Resource.ReturnTypeY = i;
1151 break;
1152 case 2:
1153 decl.Resource.ReturnTypeZ = i;
1154 break;
1155 case 3:
1156 decl.Resource.ReturnTypeW = i;
1157 break;
1158 default:
1159 assert(0);
1161 break;
1165 if (i == PIPE_TYPE_COUNT) {
1166 if (j == 0 || j > 2) {
1167 report_error(ctx, "Expected type name");
1168 return FALSE;
1170 break;
1171 } else {
1172 const char *cur2 = cur;
1173 eat_opt_white( &cur2 );
1174 if (*cur2 == ',') {
1175 cur2++;
1176 eat_opt_white( &cur2 );
1177 cur = cur2;
1178 continue;
1179 } else
1180 break;
1183 if (j < 4) {
1184 decl.Resource.ReturnTypeY =
1185 decl.Resource.ReturnTypeZ =
1186 decl.Resource.ReturnTypeW =
1187 decl.Resource.ReturnTypeX;
1189 ctx->cur = cur;
1190 } else {
1191 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1192 if (str_match_no_case( &cur, semantic_names[i] )) {
1193 const char *cur2 = cur;
1194 uint index;
1196 if (is_digit_alpha_underscore( cur ))
1197 continue;
1198 eat_opt_white( &cur2 );
1199 if (*cur2 == '[') {
1200 cur2++;
1201 eat_opt_white( &cur2 );
1202 if (!parse_uint( &cur2, &index )) {
1203 report_error( ctx, "Expected literal integer" );
1204 return FALSE;
1206 eat_opt_white( &cur2 );
1207 if (*cur2 != ']') {
1208 report_error( ctx, "Expected `]'" );
1209 return FALSE;
1211 cur2++;
1213 decl.Semantic.Index = index;
1215 cur = cur2;
1218 decl.Declaration.Semantic = 1;
1219 decl.Semantic.Name = i;
1221 ctx->cur = cur;
1222 break;
1226 } else if (is_imm_array) {
1227 unsigned i;
1228 float *vals_itr;
1229 /* we have our immediate data */
1230 if (*cur != '{') {
1231 report_error( ctx, "Immediate array without data" );
1232 return FALSE;
1234 ++cur;
1235 ctx->cur = cur;
1237 decl.ImmediateData.u =
1238 MALLOC(sizeof(union tgsi_immediate_data) * 4 *
1239 (decl.Range.Last + 1));
1240 vals_itr = (float*)decl.ImmediateData.u;
1241 for (i = 0; i <= decl.Range.Last; ++i) {
1242 if (!parse_immediate_data(ctx, vals_itr)) {
1243 FREE(decl.ImmediateData.u);
1244 return FALSE;
1246 vals_itr += 4;
1247 eat_opt_white( &ctx->cur );
1248 if (*ctx->cur != ',') {
1249 if (i != decl.Range.Last) {
1250 report_error( ctx, "Not enough data in immediate array!" );
1251 FREE(decl.ImmediateData.u);
1252 return FALSE;
1254 } else
1255 ++ctx->cur;
1257 eat_opt_white( &ctx->cur );
1258 if (*ctx->cur != '}') {
1259 FREE(decl.ImmediateData.u);
1260 report_error( ctx, "Immediate array data missing closing '}'" );
1261 return FALSE;
1263 ++ctx->cur;
1266 cur = ctx->cur;
1267 eat_opt_white( &cur );
1268 if (*cur == ',' && !is_vs_input) {
1269 uint i;
1271 cur++;
1272 eat_opt_white( &cur );
1273 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1274 if (str_match_no_case( &cur, interpolate_names[i] )) {
1275 if (is_digit_alpha_underscore( cur ))
1276 continue;
1277 decl.Declaration.Interpolate = i;
1279 ctx->cur = cur;
1280 break;
1283 if (i == TGSI_INTERPOLATE_COUNT) {
1284 report_error( ctx, "Expected semantic or interpolate attribute" );
1285 return FALSE;
1289 advance = tgsi_build_full_declaration(
1290 &decl,
1291 ctx->tokens_cur,
1292 ctx->header,
1293 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1295 if (is_imm_array)
1296 FREE(decl.ImmediateData.u);
1298 if (advance == 0)
1299 return FALSE;
1300 ctx->tokens_cur += advance;
1302 return TRUE;
1305 static boolean parse_immediate( struct translate_ctx *ctx )
1307 struct tgsi_full_immediate imm;
1308 float values[4];
1309 uint advance;
1311 if (!eat_white( &ctx->cur )) {
1312 report_error( ctx, "Syntax error" );
1313 return FALSE;
1315 if (!str_match_no_case( &ctx->cur, "FLT32" ) ||
1316 is_digit_alpha_underscore( ctx->cur )) {
1317 report_error( ctx, "Expected `FLT32'" );
1318 return FALSE;
1321 parse_immediate_data(ctx, values);
1323 imm = tgsi_default_full_immediate();
1324 imm.Immediate.NrTokens += 4;
1325 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
1326 imm.u[0].Float = values[0];
1327 imm.u[1].Float = values[1];
1328 imm.u[2].Float = values[2];
1329 imm.u[3].Float = values[3];
1331 advance = tgsi_build_full_immediate(
1332 &imm,
1333 ctx->tokens_cur,
1334 ctx->header,
1335 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1336 if (advance == 0)
1337 return FALSE;
1338 ctx->tokens_cur += advance;
1340 return TRUE;
1343 static boolean
1344 parse_primitive( const char **pcur, uint *primitive )
1346 uint i;
1348 for (i = 0; i < PIPE_PRIM_MAX; i++) {
1349 const char *cur = *pcur;
1351 if (str_match_no_case( &cur, tgsi_primitive_names[i])) {
1352 *primitive = i;
1353 *pcur = cur;
1354 return TRUE;
1357 return FALSE;
1360 static boolean
1361 parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1363 uint i;
1365 for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
1366 const char *cur = *pcur;
1368 if (str_match_no_case( &cur, tgsi_fs_coord_origin_names[i])) {
1369 *fs_coord_origin = i;
1370 *pcur = cur;
1371 return TRUE;
1374 return FALSE;
1377 static boolean
1378 parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1380 uint i;
1382 for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
1383 const char *cur = *pcur;
1385 if (str_match_no_case( &cur, tgsi_fs_coord_pixel_center_names[i])) {
1386 *fs_coord_pixel_center = i;
1387 *pcur = cur;
1388 return TRUE;
1391 return FALSE;
1395 static boolean parse_property( struct translate_ctx *ctx )
1397 struct tgsi_full_property prop;
1398 uint property_name;
1399 uint values[8];
1400 uint advance;
1401 char id[64];
1403 if (!eat_white( &ctx->cur )) {
1404 report_error( ctx, "Syntax error" );
1405 return FALSE;
1407 if (!parse_identifier( &ctx->cur, id )) {
1408 report_error( ctx, "Syntax error" );
1409 return FALSE;
1411 for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1412 ++property_name) {
1413 if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
1414 break;
1417 if (property_name >= TGSI_PROPERTY_COUNT) {
1418 debug_printf( "\nError: Unknown property : '%s'", id );
1419 return FALSE;
1422 eat_opt_white( &ctx->cur );
1423 switch(property_name) {
1424 case TGSI_PROPERTY_GS_INPUT_PRIM:
1425 case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1426 if (!parse_primitive(&ctx->cur, &values[0] )) {
1427 report_error( ctx, "Unknown primitive name as property!" );
1428 return FALSE;
1430 if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1431 ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
1432 ctx->implied_array_size = u_vertices_per_prim(values[0]);
1434 break;
1435 case TGSI_PROPERTY_FS_COORD_ORIGIN:
1436 if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1437 report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1438 return FALSE;
1440 break;
1441 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1442 if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1443 report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1444 return FALSE;
1446 break;
1447 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
1448 default:
1449 if (!parse_uint(&ctx->cur, &values[0] )) {
1450 report_error( ctx, "Expected unsigned integer as property!" );
1451 return FALSE;
1455 prop = tgsi_default_full_property();
1456 prop.Property.PropertyName = property_name;
1457 prop.Property.NrTokens += 1;
1458 prop.u[0].Data = values[0];
1460 advance = tgsi_build_full_property(
1461 &prop,
1462 ctx->tokens_cur,
1463 ctx->header,
1464 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1465 if (advance == 0)
1466 return FALSE;
1467 ctx->tokens_cur += advance;
1469 return TRUE;
1473 static boolean translate( struct translate_ctx *ctx )
1475 eat_opt_white( &ctx->cur );
1476 if (!parse_header( ctx ))
1477 return FALSE;
1479 while (*ctx->cur != '\0') {
1480 uint label_val = 0;
1481 if (!eat_white( &ctx->cur )) {
1482 report_error( ctx, "Syntax error" );
1483 return FALSE;
1486 if (*ctx->cur == '\0')
1487 break;
1488 if (parse_label( ctx, &label_val )) {
1489 if (!parse_instruction( ctx, TRUE ))
1490 return FALSE;
1492 else if (str_match_no_case( &ctx->cur, "DCL" )) {
1493 if (!parse_declaration( ctx ))
1494 return FALSE;
1496 else if (str_match_no_case( &ctx->cur, "IMM" )) {
1497 if (!parse_immediate( ctx ))
1498 return FALSE;
1500 else if (str_match_no_case( &ctx->cur, "PROPERTY" )) {
1501 if (!parse_property( ctx ))
1502 return FALSE;
1504 else if (!parse_instruction( ctx, FALSE )) {
1505 return FALSE;
1509 return TRUE;
1512 boolean
1513 tgsi_text_translate(
1514 const char *text,
1515 struct tgsi_token *tokens,
1516 uint num_tokens )
1518 struct translate_ctx ctx;
1520 ctx.text = text;
1521 ctx.cur = text;
1522 ctx.tokens = tokens;
1523 ctx.tokens_cur = tokens;
1524 ctx.tokens_end = tokens + num_tokens;
1526 if (!translate( &ctx ))
1527 return FALSE;
1529 return tgsi_sanity_check( tokens );