1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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
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"
40 static boolean
is_alpha_underscore( const char *cur
)
43 (*cur
>= 'a' && *cur
<= 'z') ||
44 (*cur
>= 'A' && *cur
<= 'Z') ||
48 static boolean
is_digit( const char *cur
)
50 return *cur
>= '0' && *cur
<= '9';
53 static boolean
is_digit_alpha_underscore( const char *cur
)
55 return is_digit( cur
) || is_alpha_underscore( cur
);
58 static char uprcase( char c
)
60 if (c
>= 'a' && c
<= 'z')
66 * Ignore case of str1 and assume str1 is already uppercase.
67 * Return TRUE iff str1 and str2 are equal.
70 streq_nocase_uprcase(const char *str1
,
73 while (*str1
&& *str2
) {
74 if (*str1
!= uprcase(*str2
))
79 return *str1
== 0 && *str2
== 0;
82 static boolean
str_match_no_case( const char **pcur
, const char *str
)
84 const char *cur
= *pcur
;
86 while (*str
!= '\0' && *str
== uprcase( *cur
)) {
97 /* Eat zero or more whitespaces.
99 static void eat_opt_white( const char **pcur
)
101 while (**pcur
== ' ' || **pcur
== '\t' || **pcur
== '\n')
105 /* Eat one or more whitespaces.
106 * Return TRUE if at least one whitespace eaten.
108 static boolean
eat_white( const char **pcur
)
110 const char *cur
= *pcur
;
112 eat_opt_white( pcur
);
116 /* Parse unsigned integer.
117 * No checks for overflow.
119 static boolean
parse_uint( const char **pcur
, uint
*val
)
121 const char *cur
= *pcur
;
123 if (is_digit( cur
)) {
125 while (is_digit( cur
))
126 *val
= *val
* 10 + *cur
++ - '0';
133 static boolean
parse_identifier( const char **pcur
, char *ret
)
135 const char *cur
= *pcur
;
137 if (is_alpha_underscore( cur
)) {
139 while (is_alpha_underscore( cur
))
148 /* Parse floating point.
150 static boolean
parse_float( const char **pcur
, float *val
)
152 const char *cur
= *pcur
;
153 boolean integral_part
= FALSE
;
154 boolean fractional_part
= FALSE
;
156 *val
= (float) atof( cur
);
158 if (*cur
== '-' || *cur
== '+')
160 if (is_digit( cur
)) {
162 integral_part
= TRUE
;
163 while (is_digit( cur
))
168 if (is_digit( cur
)) {
170 fractional_part
= TRUE
;
171 while (is_digit( cur
))
175 if (!integral_part
&& !fractional_part
)
177 if (uprcase( *cur
) == 'E') {
179 if (*cur
== '-' || *cur
== '+')
181 if (is_digit( cur
)) {
183 while (is_digit( cur
))
197 struct tgsi_token
*tokens
;
198 struct tgsi_token
*tokens_cur
;
199 struct tgsi_token
*tokens_end
;
200 struct tgsi_header
*header
;
201 unsigned processor
: 4;
202 int implied_array_size
: 5;
205 static void report_error( struct translate_ctx
*ctx
, const char *msg
)
209 const char *itr
= ctx
->text
;
211 while (itr
!= ctx
->cur
) {
220 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg
, line
, column
);
223 /* Parse shader header.
224 * Return TRUE for one of the following headers.
229 static boolean
parse_header( struct translate_ctx
*ctx
)
233 if (str_match_no_case( &ctx
->cur
, "FRAG" ))
234 processor
= TGSI_PROCESSOR_FRAGMENT
;
235 else if (str_match_no_case( &ctx
->cur
, "VERT" ))
236 processor
= TGSI_PROCESSOR_VERTEX
;
237 else if (str_match_no_case( &ctx
->cur
, "GEOM" ))
238 processor
= TGSI_PROCESSOR_GEOMETRY
;
240 report_error( ctx
, "Unknown header" );
244 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
246 ctx
->header
= (struct tgsi_header
*) ctx
->tokens_cur
++;
247 *ctx
->header
= tgsi_build_header();
249 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
251 *(struct tgsi_processor
*) ctx
->tokens_cur
++ = tgsi_build_processor( processor
, ctx
->header
);
252 ctx
->processor
= processor
;
257 static boolean
parse_label( struct translate_ctx
*ctx
, uint
*val
)
259 const char *cur
= ctx
->cur
;
261 if (parse_uint( &cur
, val
)) {
262 eat_opt_white( &cur
);
272 static const char *file_names
[TGSI_FILE_COUNT
] =
289 parse_file( const char **pcur
, uint
*file
)
293 for (i
= 0; i
< TGSI_FILE_COUNT
; i
++) {
294 const char *cur
= *pcur
;
296 if (str_match_no_case( &cur
, file_names
[i
] )) {
297 if (!is_digit_alpha_underscore( cur
)) {
309 struct translate_ctx
*ctx
,
315 eat_opt_white( &cur
);
318 *writemask
= TGSI_WRITEMASK_NONE
;
319 eat_opt_white( &cur
);
320 if (uprcase( *cur
) == 'X') {
322 *writemask
|= TGSI_WRITEMASK_X
;
324 if (uprcase( *cur
) == 'Y') {
326 *writemask
|= TGSI_WRITEMASK_Y
;
328 if (uprcase( *cur
) == 'Z') {
330 *writemask
|= TGSI_WRITEMASK_Z
;
332 if (uprcase( *cur
) == 'W') {
334 *writemask
|= TGSI_WRITEMASK_W
;
337 if (*writemask
== TGSI_WRITEMASK_NONE
) {
338 report_error( ctx
, "Writemask expected" );
345 *writemask
= TGSI_WRITEMASK_XYZW
;
351 /* <register_file_bracket> ::= <file> `['
354 parse_register_file_bracket(
355 struct translate_ctx
*ctx
,
358 if (!parse_file( &ctx
->cur
, file
)) {
359 report_error( ctx
, "Unknown register file" );
362 eat_opt_white( &ctx
->cur
);
363 if (*ctx
->cur
!= '[') {
364 report_error( ctx
, "Expected `['" );
371 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
374 parse_register_file_bracket_index(
375 struct translate_ctx
*ctx
,
381 if (!parse_register_file_bracket( ctx
, file
))
383 eat_opt_white( &ctx
->cur
);
384 if (!parse_uint( &ctx
->cur
, &uindex
)) {
385 report_error( ctx
, "Expected literal unsigned integer" );
388 *index
= (int) uindex
;
392 /* Parse simple 1d register operand.
393 * <register_dst> ::= <register_file_bracket_index> `]'
396 parse_register_1d(struct translate_ctx
*ctx
,
400 if (!parse_register_file_bracket_index( ctx
, file
, index
))
402 eat_opt_white( &ctx
->cur
);
403 if (*ctx
->cur
!= ']') {
404 report_error( ctx
, "Expected `]'" );
411 struct parsed_bracket
{
421 parse_register_bracket(
422 struct translate_ctx
*ctx
,
423 struct parsed_bracket
*brackets
)
428 memset(brackets
, 0, sizeof(struct parsed_bracket
));
430 eat_opt_white( &ctx
->cur
);
433 if (parse_file( &cur
, &brackets
->ind_file
)) {
434 if (!parse_register_1d( ctx
, &brackets
->ind_file
,
435 &brackets
->ind_index
))
437 eat_opt_white( &ctx
->cur
);
439 if (*ctx
->cur
== '.') {
441 eat_opt_white(&ctx
->cur
);
443 switch (uprcase(*ctx
->cur
)) {
445 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
448 brackets
->ind_comp
= TGSI_SWIZZLE_Y
;
451 brackets
->ind_comp
= TGSI_SWIZZLE_Z
;
454 brackets
->ind_comp
= TGSI_SWIZZLE_W
;
457 report_error(ctx
, "Expected indirect register swizzle component `x', `y', `z' or `w'");
461 eat_opt_white(&ctx
->cur
);
464 if (*ctx
->cur
== '+' || *ctx
->cur
== '-') {
467 negate
= *ctx
->cur
== '-';
469 eat_opt_white( &ctx
->cur
);
470 if (!parse_uint( &ctx
->cur
, &uindex
)) {
471 report_error( ctx
, "Expected literal unsigned integer" );
475 brackets
->index
= -(int) uindex
;
477 brackets
->index
= (int) uindex
;
484 if (!parse_uint( &ctx
->cur
, &uindex
)) {
485 report_error( ctx
, "Expected literal unsigned integer" );
488 brackets
->index
= (int) uindex
;
489 brackets
->ind_file
= TGSI_FILE_NULL
;
490 brackets
->ind_index
= 0;
492 eat_opt_white( &ctx
->cur
);
493 if (*ctx
->cur
!= ']') {
494 report_error( ctx
, "Expected `]'" );
502 parse_opt_register_src_bracket(
503 struct translate_ctx
*ctx
,
504 struct parsed_bracket
*brackets
,
505 int *parsed_brackets
)
507 const char *cur
= ctx
->cur
;
509 *parsed_brackets
= 0;
511 eat_opt_white( &cur
);
516 if (!parse_register_bracket(ctx
, brackets
))
519 *parsed_brackets
= 1;
526 /* Parse source register operand.
527 * <register_src> ::= <register_file_bracket_index> `]' |
528 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
529 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
530 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
534 struct translate_ctx
*ctx
,
536 struct parsed_bracket
*brackets
)
538 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
539 if (!parse_register_file_bracket( ctx
, file
))
541 if (!parse_register_bracket( ctx
, brackets
))
547 struct parsed_dcl_bracket
{
553 parse_register_dcl_bracket(
554 struct translate_ctx
*ctx
,
555 struct parsed_dcl_bracket
*bracket
)
558 memset(bracket
, 0, sizeof(struct parsed_dcl_bracket
));
560 eat_opt_white( &ctx
->cur
);
562 if (!parse_uint( &ctx
->cur
, &uindex
)) {
563 /* it can be an empty bracket [] which means its range
564 * is from 0 to some implied size */
565 if (ctx
->cur
[0] == ']' && ctx
->implied_array_size
!= 0) {
567 bracket
->last
= ctx
->implied_array_size
- 1;
570 report_error( ctx
, "Expected literal unsigned integer" );
573 bracket
->first
= uindex
;
575 eat_opt_white( &ctx
->cur
);
577 if (ctx
->cur
[0] == '.' && ctx
->cur
[1] == '.') {
581 eat_opt_white( &ctx
->cur
);
582 if (!parse_uint( &ctx
->cur
, &uindex
)) {
583 report_error( ctx
, "Expected literal integer" );
586 bracket
->last
= (int) uindex
;
587 eat_opt_white( &ctx
->cur
);
590 bracket
->last
= bracket
->first
;
594 if (*ctx
->cur
!= ']') {
595 report_error( ctx
, "Expected `]' or `..'" );
602 /* Parse register declaration.
603 * <register_dcl> ::= <register_file_bracket_index> `]' |
604 * <register_file_bracket_index> `..' <index> `]'
608 struct translate_ctx
*ctx
,
610 struct parsed_dcl_bracket
*brackets
,
617 if (!parse_register_file_bracket( ctx
, file
))
619 if (!parse_register_dcl_bracket( ctx
, &brackets
[0] ))
625 eat_opt_white( &cur
);
630 if (!parse_register_dcl_bracket( ctx
, &brackets
[1] ))
632 /* for geometry shader we don't really care about
633 * the first brackets it's always the size of the
634 * input primitive. so we want to declare just
635 * the index relevant to the semantics which is in
636 * the second bracket */
637 if (ctx
->processor
== TGSI_PROCESSOR_GEOMETRY
&& *file
== TGSI_FILE_INPUT
) {
638 brackets
[0] = brackets
[1];
649 /* Parse destination register operand.*/
652 struct translate_ctx
*ctx
,
654 struct parsed_bracket
*brackets
)
656 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
657 if (!parse_register_file_bracket( ctx
, file
))
659 if (!parse_register_bracket( ctx
, brackets
))
667 struct translate_ctx
*ctx
,
668 struct tgsi_full_dst_register
*dst
)
673 struct parsed_bracket bracket
[2];
674 int parsed_opt_brackets
;
676 if (!parse_register_dst( ctx
, &file
, &bracket
[0] ))
678 if (!parse_opt_register_src_bracket(ctx
, &bracket
[1], &parsed_opt_brackets
))
682 eat_opt_white( &cur
);
684 if (!parse_opt_writemask( ctx
, &writemask
))
687 dst
->Register
.File
= file
;
688 if (parsed_opt_brackets
) {
689 dst
->Register
.Dimension
= 1;
690 dst
->Dimension
.Indirect
= 0;
691 dst
->Dimension
.Dimension
= 0;
692 dst
->Dimension
.Index
= bracket
[0].index
;
693 bracket
[0] = bracket
[1];
695 dst
->Register
.Index
= bracket
[0].index
;
696 dst
->Register
.WriteMask
= writemask
;
697 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
698 dst
->Register
.Indirect
= 1;
699 dst
->Indirect
.File
= bracket
[0].ind_file
;
700 dst
->Indirect
.Index
= bracket
[0].ind_index
;
701 dst
->Indirect
.SwizzleX
= bracket
[0].ind_comp
;
702 dst
->Indirect
.SwizzleY
= bracket
[0].ind_comp
;
703 dst
->Indirect
.SwizzleZ
= bracket
[0].ind_comp
;
704 dst
->Indirect
.SwizzleW
= bracket
[0].ind_comp
;
710 parse_optional_swizzle(
711 struct translate_ctx
*ctx
,
713 boolean
*parsed_swizzle
)
715 const char *cur
= ctx
->cur
;
717 *parsed_swizzle
= FALSE
;
719 eat_opt_white( &cur
);
724 eat_opt_white( &cur
);
725 for (i
= 0; i
< 4; i
++) {
726 if (uprcase( *cur
) == 'X')
727 swizzle
[i
] = TGSI_SWIZZLE_X
;
728 else if (uprcase( *cur
) == 'Y')
729 swizzle
[i
] = TGSI_SWIZZLE_Y
;
730 else if (uprcase( *cur
) == 'Z')
731 swizzle
[i
] = TGSI_SWIZZLE_Z
;
732 else if (uprcase( *cur
) == 'W')
733 swizzle
[i
] = TGSI_SWIZZLE_W
;
735 report_error( ctx
, "Expected register swizzle component `x', `y', `z' or `w'" );
740 *parsed_swizzle
= TRUE
;
748 struct translate_ctx
*ctx
,
749 struct tgsi_full_src_register
*src
)
753 boolean parsed_swizzle
;
754 struct parsed_bracket bracket
[2];
755 int parsed_opt_brackets
;
757 if (*ctx
->cur
== '-') {
759 eat_opt_white( &ctx
->cur
);
760 src
->Register
.Negate
= 1;
763 if (*ctx
->cur
== '|') {
765 eat_opt_white( &ctx
->cur
);
766 src
->Register
.Absolute
= 1;
769 if (!parse_register_src(ctx
, &file
, &bracket
[0]))
771 if (!parse_opt_register_src_bracket(ctx
, &bracket
[1], &parsed_opt_brackets
))
774 src
->Register
.File
= file
;
775 if (parsed_opt_brackets
) {
776 src
->Register
.Dimension
= 1;
777 src
->Dimension
.Indirect
= 0;
778 src
->Dimension
.Dimension
= 0;
779 src
->Dimension
.Index
= bracket
[0].index
;
780 bracket
[0] = bracket
[1];
782 src
->Register
.Index
= bracket
[0].index
;
783 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
784 src
->Register
.Indirect
= 1;
785 src
->Indirect
.File
= bracket
[0].ind_file
;
786 src
->Indirect
.Index
= bracket
[0].ind_index
;
787 src
->Indirect
.SwizzleX
= bracket
[0].ind_comp
;
788 src
->Indirect
.SwizzleY
= bracket
[0].ind_comp
;
789 src
->Indirect
.SwizzleZ
= bracket
[0].ind_comp
;
790 src
->Indirect
.SwizzleW
= bracket
[0].ind_comp
;
793 /* Parse optional swizzle.
795 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
)) {
796 if (parsed_swizzle
) {
797 src
->Register
.SwizzleX
= swizzle
[0];
798 src
->Register
.SwizzleY
= swizzle
[1];
799 src
->Register
.SwizzleZ
= swizzle
[2];
800 src
->Register
.SwizzleW
= swizzle
[3];
804 if (src
->Register
.Absolute
) {
805 eat_opt_white( &ctx
->cur
);
806 if (*ctx
->cur
!= '|') {
807 report_error( ctx
, "Expected `|'" );
817 static const char *texture_names
[TGSI_TEXTURE_COUNT
] =
831 match_inst_mnemonic(const char **pcur
,
832 const struct tgsi_opcode_info
*info
)
834 if (str_match_no_case(pcur
, info
->mnemonic
)) {
842 struct translate_ctx
*ctx
,
846 uint saturate
= TGSI_SAT_NONE
;
847 const struct tgsi_opcode_info
*info
;
848 struct tgsi_full_instruction inst
;
851 inst
= tgsi_default_full_instruction();
855 eat_opt_white( &ctx
->cur
);
856 if (*ctx
->cur
== '(') {
860 boolean parsed_swizzle
;
862 inst
.Instruction
.Predicate
= 1;
865 if (*ctx
->cur
== '!') {
867 inst
.Predicate
.Negate
= 1;
870 if (!parse_register_1d( ctx
, &file
, &index
))
873 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
)) {
874 if (parsed_swizzle
) {
875 inst
.Predicate
.SwizzleX
= swizzle
[0];
876 inst
.Predicate
.SwizzleY
= swizzle
[1];
877 inst
.Predicate
.SwizzleZ
= swizzle
[2];
878 inst
.Predicate
.SwizzleW
= swizzle
[3];
882 if (*ctx
->cur
!= ')') {
883 report_error( ctx
, "Expected `)'" );
890 /* Parse instruction name.
892 eat_opt_white( &ctx
->cur
);
893 for (i
= 0; i
< TGSI_OPCODE_LAST
; i
++) {
894 const char *cur
= ctx
->cur
;
896 info
= tgsi_get_opcode_info( i
);
897 if (match_inst_mnemonic(&cur
, info
)) {
898 if (str_match_no_case( &cur
, "_SATNV" ))
899 saturate
= TGSI_SAT_MINUS_PLUS_ONE
;
900 else if (str_match_no_case( &cur
, "_SAT" ))
901 saturate
= TGSI_SAT_ZERO_ONE
;
903 if (info
->num_dst
+ info
->num_src
+ info
->is_tex
== 0) {
904 if (!is_digit_alpha_underscore( cur
)) {
909 else if (*cur
== '\0' || eat_white( &cur
)) {
915 if (i
== TGSI_OPCODE_LAST
) {
917 report_error( ctx
, "Unknown opcode" );
919 report_error( ctx
, "Expected `DCL', `IMM' or a label" );
923 inst
.Instruction
.Opcode
= i
;
924 inst
.Instruction
.Saturate
= saturate
;
925 inst
.Instruction
.NumDstRegs
= info
->num_dst
;
926 inst
.Instruction
.NumSrcRegs
= info
->num_src
;
928 /* Parse instruction operands.
930 for (i
= 0; i
< info
->num_dst
+ info
->num_src
+ info
->is_tex
; i
++) {
932 eat_opt_white( &ctx
->cur
);
933 if (*ctx
->cur
!= ',') {
934 report_error( ctx
, "Expected `,'" );
938 eat_opt_white( &ctx
->cur
);
941 if (i
< info
->num_dst
) {
942 if (!parse_dst_operand( ctx
, &inst
.Dst
[i
] ))
945 else if (i
< info
->num_dst
+ info
->num_src
) {
946 if (!parse_src_operand( ctx
, &inst
.Src
[i
- info
->num_dst
] ))
952 for (j
= 0; j
< TGSI_TEXTURE_COUNT
; j
++) {
953 if (str_match_no_case( &ctx
->cur
, texture_names
[j
] )) {
954 if (!is_digit_alpha_underscore( ctx
->cur
)) {
955 inst
.Instruction
.Texture
= 1;
956 inst
.Texture
.Texture
= j
;
961 if (j
== TGSI_TEXTURE_COUNT
) {
962 report_error( ctx
, "Expected texture target" );
968 if (info
->is_branch
) {
971 eat_opt_white( &ctx
->cur
);
972 if (*ctx
->cur
!= ':') {
973 report_error( ctx
, "Expected `:'" );
977 eat_opt_white( &ctx
->cur
);
978 if (!parse_uint( &ctx
->cur
, &target
)) {
979 report_error( ctx
, "Expected a label" );
982 inst
.Instruction
.Label
= 1;
983 inst
.Label
.Label
= target
;
986 advance
= tgsi_build_full_instruction(
990 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
993 ctx
->tokens_cur
+= advance
;
998 static const char *semantic_names
[TGSI_SEMANTIC_COUNT
] =
1014 static const char *interpolate_names
[TGSI_INTERPOLATE_COUNT
] =
1022 /* parses a 4-touple of the form {x, y, z, w}
1023 * where x, y, z, w are numbers */
1024 static boolean
parse_immediate_data(struct translate_ctx
*ctx
,
1029 eat_opt_white( &ctx
->cur
);
1030 if (*ctx
->cur
!= '{') {
1031 report_error( ctx
, "Expected `{'" );
1035 for (i
= 0; i
< 4; i
++) {
1036 eat_opt_white( &ctx
->cur
);
1038 if (*ctx
->cur
!= ',') {
1039 report_error( ctx
, "Expected `,'" );
1043 eat_opt_white( &ctx
->cur
);
1045 if (!parse_float( &ctx
->cur
, &values
[i
] )) {
1046 report_error( ctx
, "Expected literal floating point" );
1050 eat_opt_white( &ctx
->cur
);
1051 if (*ctx
->cur
!= '}') {
1052 report_error( ctx
, "Expected `}'" );
1060 static boolean
parse_declaration( struct translate_ctx
*ctx
)
1062 struct tgsi_full_declaration decl
;
1064 struct parsed_dcl_bracket brackets
[2];
1069 boolean is_vs_input
;
1070 boolean is_imm_array
;
1072 assert(Elements(semantic_names
) == TGSI_SEMANTIC_COUNT
);
1073 assert(Elements(interpolate_names
) == TGSI_INTERPOLATE_COUNT
);
1075 if (!eat_white( &ctx
->cur
)) {
1076 report_error( ctx
, "Syntax error" );
1079 if (!parse_register_dcl( ctx
, &file
, brackets
, &num_brackets
))
1081 if (!parse_opt_writemask( ctx
, &writemask
))
1084 decl
= tgsi_default_full_declaration();
1085 decl
.Declaration
.File
= file
;
1086 decl
.Declaration
.UsageMask
= writemask
;
1088 if (num_brackets
== 1) {
1089 decl
.Range
.First
= brackets
[0].first
;
1090 decl
.Range
.Last
= brackets
[0].last
;
1092 decl
.Range
.First
= brackets
[1].first
;
1093 decl
.Range
.Last
= brackets
[1].last
;
1095 decl
.Declaration
.Dimension
= 1;
1096 decl
.Dim
.Index2D
= brackets
[0].first
;
1099 is_vs_input
= (file
== TGSI_FILE_INPUT
&&
1100 ctx
->processor
== TGSI_PROCESSOR_VERTEX
);
1101 is_imm_array
= (file
== TGSI_FILE_IMMEDIATE_ARRAY
);
1104 eat_opt_white( &cur
);
1105 if (*cur
== ',' && !is_vs_input
) {
1109 eat_opt_white( &cur
);
1110 for (i
= 0; i
< TGSI_SEMANTIC_COUNT
; i
++) {
1111 if (str_match_no_case( &cur
, semantic_names
[i
] )) {
1112 const char *cur2
= cur
;
1115 if (is_digit_alpha_underscore( cur
))
1117 eat_opt_white( &cur2
);
1120 eat_opt_white( &cur2
);
1121 if (!parse_uint( &cur2
, &index
)) {
1122 report_error( ctx
, "Expected literal integer" );
1125 eat_opt_white( &cur2
);
1127 report_error( ctx
, "Expected `]'" );
1132 decl
.Semantic
.Index
= index
;
1137 decl
.Declaration
.Semantic
= 1;
1138 decl
.Semantic
.Name
= i
;
1144 } else if (is_imm_array
) {
1147 /* we have our immediate data */
1149 report_error( ctx
, "Immediate array without data" );
1155 decl
.ImmediateData
.u
=
1156 MALLOC(sizeof(union tgsi_immediate_data
) * 4 *
1157 (decl
.Range
.Last
+ 1));
1158 vals_itr
= (float*)decl
.ImmediateData
.u
;
1159 for (i
= 0; i
<= decl
.Range
.Last
; ++i
) {
1160 if (!parse_immediate_data(ctx
, vals_itr
)) {
1161 FREE(decl
.ImmediateData
.u
);
1165 eat_opt_white( &ctx
->cur
);
1166 if (*ctx
->cur
!= ',') {
1167 if (i
!= decl
.Range
.Last
) {
1168 report_error( ctx
, "Not enough data in immediate array!" );
1169 FREE(decl
.ImmediateData
.u
);
1175 eat_opt_white( &ctx
->cur
);
1176 if (*ctx
->cur
!= '}') {
1177 FREE(decl
.ImmediateData
.u
);
1178 report_error( ctx
, "Immediate array data missing closing '}'" );
1185 eat_opt_white( &cur
);
1186 if (*cur
== ',' && !is_vs_input
) {
1190 eat_opt_white( &cur
);
1191 for (i
= 0; i
< TGSI_INTERPOLATE_COUNT
; i
++) {
1192 if (str_match_no_case( &cur
, interpolate_names
[i
] )) {
1193 if (is_digit_alpha_underscore( cur
))
1195 decl
.Declaration
.Interpolate
= i
;
1201 if (i
== TGSI_INTERPOLATE_COUNT
) {
1202 report_error( ctx
, "Expected semantic or interpolate attribute" );
1207 advance
= tgsi_build_full_declaration(
1211 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1214 FREE(decl
.ImmediateData
.u
);
1218 ctx
->tokens_cur
+= advance
;
1223 static boolean
parse_immediate( struct translate_ctx
*ctx
)
1225 struct tgsi_full_immediate imm
;
1229 if (!eat_white( &ctx
->cur
)) {
1230 report_error( ctx
, "Syntax error" );
1233 if (!str_match_no_case( &ctx
->cur
, "FLT32" ) ||
1234 is_digit_alpha_underscore( ctx
->cur
)) {
1235 report_error( ctx
, "Expected `FLT32'" );
1239 parse_immediate_data(ctx
, values
);
1241 imm
= tgsi_default_full_immediate();
1242 imm
.Immediate
.NrTokens
+= 4;
1243 imm
.Immediate
.DataType
= TGSI_IMM_FLOAT32
;
1244 imm
.u
[0].Float
= values
[0];
1245 imm
.u
[1].Float
= values
[1];
1246 imm
.u
[2].Float
= values
[2];
1247 imm
.u
[3].Float
= values
[3];
1249 advance
= tgsi_build_full_immediate(
1253 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1256 ctx
->tokens_cur
+= advance
;
1261 static const char *property_names
[] =
1263 "GS_INPUT_PRIMITIVE",
1264 "GS_OUTPUT_PRIMITIVE",
1265 "GS_MAX_OUTPUT_VERTICES",
1267 "FS_COORD_PIXEL_CENTER",
1268 "FS_COLOR0_WRITE_ALL_CBUFS"
1271 static const char *primitive_names
[] =
1285 static const char *fs_coord_origin_names
[] =
1291 static const char *fs_coord_pixel_center_names
[] =
1299 parse_primitive( const char **pcur
, uint
*primitive
)
1303 for (i
= 0; i
< PIPE_PRIM_MAX
; i
++) {
1304 const char *cur
= *pcur
;
1306 if (str_match_no_case( &cur
, primitive_names
[i
])) {
1316 parse_fs_coord_origin( const char **pcur
, uint
*fs_coord_origin
)
1320 for (i
= 0; i
< sizeof(fs_coord_origin_names
) / sizeof(fs_coord_origin_names
[0]); i
++) {
1321 const char *cur
= *pcur
;
1323 if (str_match_no_case( &cur
, fs_coord_origin_names
[i
])) {
1324 *fs_coord_origin
= i
;
1333 parse_fs_coord_pixel_center( const char **pcur
, uint
*fs_coord_pixel_center
)
1337 for (i
= 0; i
< sizeof(fs_coord_pixel_center_names
) / sizeof(fs_coord_pixel_center_names
[0]); i
++) {
1338 const char *cur
= *pcur
;
1340 if (str_match_no_case( &cur
, fs_coord_pixel_center_names
[i
])) {
1341 *fs_coord_pixel_center
= i
;
1350 static boolean
parse_property( struct translate_ctx
*ctx
)
1352 struct tgsi_full_property prop
;
1358 if (!eat_white( &ctx
->cur
)) {
1359 report_error( ctx
, "Syntax error" );
1362 if (!parse_identifier( &ctx
->cur
, id
)) {
1363 report_error( ctx
, "Syntax error" );
1366 for (property_name
= 0; property_name
< TGSI_PROPERTY_COUNT
;
1368 if (streq_nocase_uprcase(property_names
[property_name
], id
)) {
1372 if (property_name
>= TGSI_PROPERTY_COUNT
) {
1373 debug_printf( "\nError: Unknown property : '%s'", id
);
1377 eat_opt_white( &ctx
->cur
);
1378 switch(property_name
) {
1379 case TGSI_PROPERTY_GS_INPUT_PRIM
:
1380 case TGSI_PROPERTY_GS_OUTPUT_PRIM
:
1381 if (!parse_primitive(&ctx
->cur
, &values
[0] )) {
1382 report_error( ctx
, "Unknown primitive name as property!" );
1385 if (property_name
== TGSI_PROPERTY_GS_INPUT_PRIM
&&
1386 ctx
->processor
== TGSI_PROCESSOR_GEOMETRY
) {
1387 ctx
->implied_array_size
= u_vertices_per_prim(values
[0]);
1390 case TGSI_PROPERTY_FS_COORD_ORIGIN
:
1391 if (!parse_fs_coord_origin(&ctx
->cur
, &values
[0] )) {
1392 report_error( ctx
, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1396 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER
:
1397 if (!parse_fs_coord_pixel_center(&ctx
->cur
, &values
[0] )) {
1398 report_error( ctx
, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1402 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS
:
1405 if (!parse_uint(&ctx
->cur
, &values
[0] )) {
1406 report_error( ctx
, "Expected unsigned integer as property!" );
1411 prop
= tgsi_default_full_property();
1412 prop
.Property
.PropertyName
= property_name
;
1413 prop
.Property
.NrTokens
+= 1;
1414 prop
.u
[0].Data
= values
[0];
1416 advance
= tgsi_build_full_property(
1420 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1423 ctx
->tokens_cur
+= advance
;
1429 static boolean
translate( struct translate_ctx
*ctx
)
1431 eat_opt_white( &ctx
->cur
);
1432 if (!parse_header( ctx
))
1435 while (*ctx
->cur
!= '\0') {
1437 if (!eat_white( &ctx
->cur
)) {
1438 report_error( ctx
, "Syntax error" );
1442 if (*ctx
->cur
== '\0')
1444 if (parse_label( ctx
, &label_val
)) {
1445 if (!parse_instruction( ctx
, TRUE
))
1448 else if (str_match_no_case( &ctx
->cur
, "DCL" )) {
1449 if (!parse_declaration( ctx
))
1452 else if (str_match_no_case( &ctx
->cur
, "IMM" )) {
1453 if (!parse_immediate( ctx
))
1456 else if (str_match_no_case( &ctx
->cur
, "PROPERTY" )) {
1457 if (!parse_property( ctx
))
1460 else if (!parse_instruction( ctx
, FALSE
)) {
1469 tgsi_text_translate(
1471 struct tgsi_token
*tokens
,
1474 struct translate_ctx ctx
;
1478 ctx
.tokens
= tokens
;
1479 ctx
.tokens_cur
= tokens
;
1480 ctx
.tokens_end
= tokens
+ num_tokens
;
1482 if (!translate( &ctx
))
1485 return tgsi_sanity_check( tokens
);