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_strings.h"
39 #include "tgsi_util.h"
40 #include "tgsi_dump.h"
42 static boolean
is_alpha_underscore( const char *cur
)
45 (*cur
>= 'a' && *cur
<= 'z') ||
46 (*cur
>= 'A' && *cur
<= 'Z') ||
50 static boolean
is_digit( const char *cur
)
52 return *cur
>= '0' && *cur
<= '9';
55 static boolean
is_digit_alpha_underscore( const char *cur
)
57 return is_digit( cur
) || is_alpha_underscore( cur
);
60 static char uprcase( char c
)
62 if (c
>= 'a' && c
<= 'z')
68 * Ignore case of str1 and assume str1 is already uppercase.
69 * Return TRUE iff str1 and str2 are equal.
72 streq_nocase_uprcase(const char *str1
,
75 while (*str1
&& *str2
) {
76 if (*str1
!= uprcase(*str2
))
81 return *str1
== 0 && *str2
== 0;
84 /* Return TRUE if both strings match.
85 * The second string is terminated by zero.
86 * The pointer to the first string is moved at end of the read word
89 static boolean
str_match_no_case( const char **pcur
, const char *str
)
91 const char *cur
= *pcur
;
93 while (*str
!= '\0' && *str
== uprcase( *cur
)) {
104 /* Return TRUE if both strings match.
105 * The first string is be terminated by a non-digit non-letter non-underscore
106 * character, the second string is terminated by zero.
107 * The pointer to the first string is moved at end of the read word
110 static boolean
str_match_nocase_whole( const char **pcur
, const char *str
)
112 const char *cur
= *pcur
;
114 if (str_match_no_case(&cur
, str
) &&
115 !is_digit_alpha_underscore(cur
)) {
122 /* Eat zero or more whitespaces.
124 static void eat_opt_white( const char **pcur
)
126 while (**pcur
== ' ' || **pcur
== '\t' || **pcur
== '\n')
130 /* Eat one or more whitespaces.
131 * Return TRUE if at least one whitespace eaten.
133 static boolean
eat_white( const char **pcur
)
135 const char *cur
= *pcur
;
137 eat_opt_white( pcur
);
141 /* Parse unsigned integer.
142 * No checks for overflow.
144 static boolean
parse_uint( const char **pcur
, uint
*val
)
146 const char *cur
= *pcur
;
148 if (is_digit( cur
)) {
150 while (is_digit( cur
))
151 *val
= *val
* 10 + *cur
++ - '0';
158 static boolean
parse_int( const char **pcur
, int *val
)
160 const char *cur
= *pcur
;
161 int sign
= (*cur
== '-' ? -1 : 1);
163 if (*cur
== '+' || *cur
== '-')
166 if (parse_uint(&cur
, (uint
*)val
)) {
175 static boolean
parse_identifier( const char **pcur
, char *ret
)
177 const char *cur
= *pcur
;
179 if (is_alpha_underscore( cur
)) {
181 while (is_alpha_underscore( cur
) || is_digit( cur
))
190 /* Parse floating point.
192 static boolean
parse_float( const char **pcur
, float *val
)
194 const char *cur
= *pcur
;
195 boolean integral_part
= FALSE
;
196 boolean fractional_part
= FALSE
;
198 *val
= (float) atof( cur
);
200 if (*cur
== '-' || *cur
== '+')
202 if (is_digit( cur
)) {
204 integral_part
= TRUE
;
205 while (is_digit( cur
))
210 if (is_digit( cur
)) {
212 fractional_part
= TRUE
;
213 while (is_digit( cur
))
217 if (!integral_part
&& !fractional_part
)
219 if (uprcase( *cur
) == 'E') {
221 if (*cur
== '-' || *cur
== '+')
223 if (is_digit( cur
)) {
225 while (is_digit( cur
))
239 struct tgsi_token
*tokens
;
240 struct tgsi_token
*tokens_cur
;
241 struct tgsi_token
*tokens_end
;
242 struct tgsi_header
*header
;
243 unsigned processor
: 4;
244 int implied_array_size
: 5;
245 unsigned num_immediates
;
248 static void report_error( struct translate_ctx
*ctx
, const char *msg
)
252 const char *itr
= ctx
->text
;
254 while (itr
!= ctx
->cur
) {
263 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg
, line
, column
);
266 /* Parse shader header.
267 * Return TRUE for one of the following headers.
272 static boolean
parse_header( struct translate_ctx
*ctx
)
276 if (str_match_nocase_whole( &ctx
->cur
, "FRAG" ))
277 processor
= TGSI_PROCESSOR_FRAGMENT
;
278 else if (str_match_nocase_whole( &ctx
->cur
, "VERT" ))
279 processor
= TGSI_PROCESSOR_VERTEX
;
280 else if (str_match_nocase_whole( &ctx
->cur
, "GEOM" ))
281 processor
= TGSI_PROCESSOR_GEOMETRY
;
282 else if (str_match_nocase_whole( &ctx
->cur
, "COMP" ))
283 processor
= TGSI_PROCESSOR_COMPUTE
;
285 report_error( ctx
, "Unknown header" );
289 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
291 ctx
->header
= (struct tgsi_header
*) ctx
->tokens_cur
++;
292 *ctx
->header
= tgsi_build_header();
294 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
296 *(struct tgsi_processor
*) ctx
->tokens_cur
++ = tgsi_build_processor( processor
, ctx
->header
);
297 ctx
->processor
= processor
;
302 static boolean
parse_label( struct translate_ctx
*ctx
, uint
*val
)
304 const char *cur
= ctx
->cur
;
306 if (parse_uint( &cur
, val
)) {
307 eat_opt_white( &cur
);
318 parse_file( const char **pcur
, uint
*file
)
322 for (i
= 0; i
< TGSI_FILE_COUNT
; i
++) {
323 const char *cur
= *pcur
;
325 if (str_match_nocase_whole( &cur
, tgsi_file_names
[i
] )) {
336 struct translate_ctx
*ctx
,
342 eat_opt_white( &cur
);
345 *writemask
= TGSI_WRITEMASK_NONE
;
346 eat_opt_white( &cur
);
347 if (uprcase( *cur
) == 'X') {
349 *writemask
|= TGSI_WRITEMASK_X
;
351 if (uprcase( *cur
) == 'Y') {
353 *writemask
|= TGSI_WRITEMASK_Y
;
355 if (uprcase( *cur
) == 'Z') {
357 *writemask
|= TGSI_WRITEMASK_Z
;
359 if (uprcase( *cur
) == 'W') {
361 *writemask
|= TGSI_WRITEMASK_W
;
364 if (*writemask
== TGSI_WRITEMASK_NONE
) {
365 report_error( ctx
, "Writemask expected" );
372 *writemask
= TGSI_WRITEMASK_XYZW
;
378 /* <register_file_bracket> ::= <file> `['
381 parse_register_file_bracket(
382 struct translate_ctx
*ctx
,
385 if (!parse_file( &ctx
->cur
, file
)) {
386 report_error( ctx
, "Unknown register file" );
389 eat_opt_white( &ctx
->cur
);
390 if (*ctx
->cur
!= '[') {
391 report_error( ctx
, "Expected `['" );
398 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
401 parse_register_file_bracket_index(
402 struct translate_ctx
*ctx
,
408 if (!parse_register_file_bracket( ctx
, file
))
410 eat_opt_white( &ctx
->cur
);
411 if (!parse_uint( &ctx
->cur
, &uindex
)) {
412 report_error( ctx
, "Expected literal unsigned integer" );
415 *index
= (int) uindex
;
419 /* Parse simple 1d register operand.
420 * <register_dst> ::= <register_file_bracket_index> `]'
423 parse_register_1d(struct translate_ctx
*ctx
,
427 if (!parse_register_file_bracket_index( ctx
, file
, index
))
429 eat_opt_white( &ctx
->cur
);
430 if (*ctx
->cur
!= ']') {
431 report_error( ctx
, "Expected `]'" );
438 struct parsed_bracket
{
448 parse_register_bracket(
449 struct translate_ctx
*ctx
,
450 struct parsed_bracket
*brackets
)
455 memset(brackets
, 0, sizeof(struct parsed_bracket
));
457 eat_opt_white( &ctx
->cur
);
460 if (parse_file( &cur
, &brackets
->ind_file
)) {
461 if (!parse_register_1d( ctx
, &brackets
->ind_file
,
462 &brackets
->ind_index
))
464 eat_opt_white( &ctx
->cur
);
466 if (*ctx
->cur
== '.') {
468 eat_opt_white(&ctx
->cur
);
470 switch (uprcase(*ctx
->cur
)) {
472 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
475 brackets
->ind_comp
= TGSI_SWIZZLE_Y
;
478 brackets
->ind_comp
= TGSI_SWIZZLE_Z
;
481 brackets
->ind_comp
= TGSI_SWIZZLE_W
;
484 report_error(ctx
, "Expected indirect register swizzle component `x', `y', `z' or `w'");
488 eat_opt_white(&ctx
->cur
);
491 if (*ctx
->cur
== '+' || *ctx
->cur
== '-')
492 parse_int( &ctx
->cur
, &brackets
->index
);
497 if (!parse_uint( &ctx
->cur
, &uindex
)) {
498 report_error( ctx
, "Expected literal unsigned integer" );
501 brackets
->index
= (int) uindex
;
502 brackets
->ind_file
= TGSI_FILE_NULL
;
503 brackets
->ind_index
= 0;
505 eat_opt_white( &ctx
->cur
);
506 if (*ctx
->cur
!= ']') {
507 report_error( ctx
, "Expected `]'" );
515 parse_opt_register_src_bracket(
516 struct translate_ctx
*ctx
,
517 struct parsed_bracket
*brackets
,
518 int *parsed_brackets
)
520 const char *cur
= ctx
->cur
;
522 *parsed_brackets
= 0;
524 eat_opt_white( &cur
);
529 if (!parse_register_bracket(ctx
, brackets
))
532 *parsed_brackets
= 1;
539 /* Parse source register operand.
540 * <register_src> ::= <register_file_bracket_index> `]' |
541 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
542 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
543 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
547 struct translate_ctx
*ctx
,
549 struct parsed_bracket
*brackets
)
551 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
552 if (!parse_register_file_bracket( ctx
, file
))
554 if (!parse_register_bracket( ctx
, brackets
))
560 struct parsed_dcl_bracket
{
566 parse_register_dcl_bracket(
567 struct translate_ctx
*ctx
,
568 struct parsed_dcl_bracket
*bracket
)
571 memset(bracket
, 0, sizeof(struct parsed_dcl_bracket
));
573 eat_opt_white( &ctx
->cur
);
575 if (!parse_uint( &ctx
->cur
, &uindex
)) {
576 /* it can be an empty bracket [] which means its range
577 * is from 0 to some implied size */
578 if (ctx
->cur
[0] == ']' && ctx
->implied_array_size
!= 0) {
580 bracket
->last
= ctx
->implied_array_size
- 1;
583 report_error( ctx
, "Expected literal unsigned integer" );
586 bracket
->first
= uindex
;
588 eat_opt_white( &ctx
->cur
);
590 if (ctx
->cur
[0] == '.' && ctx
->cur
[1] == '.') {
594 eat_opt_white( &ctx
->cur
);
595 if (!parse_uint( &ctx
->cur
, &uindex
)) {
596 report_error( ctx
, "Expected literal integer" );
599 bracket
->last
= (int) uindex
;
600 eat_opt_white( &ctx
->cur
);
603 bracket
->last
= bracket
->first
;
607 if (*ctx
->cur
!= ']') {
608 report_error( ctx
, "Expected `]' or `..'" );
615 /* Parse register declaration.
616 * <register_dcl> ::= <register_file_bracket_index> `]' |
617 * <register_file_bracket_index> `..' <index> `]'
621 struct translate_ctx
*ctx
,
623 struct parsed_dcl_bracket
*brackets
,
630 if (!parse_register_file_bracket( ctx
, file
))
632 if (!parse_register_dcl_bracket( ctx
, &brackets
[0] ))
638 eat_opt_white( &cur
);
643 if (!parse_register_dcl_bracket( ctx
, &brackets
[1] ))
645 /* for geometry shader we don't really care about
646 * the first brackets it's always the size of the
647 * input primitive. so we want to declare just
648 * the index relevant to the semantics which is in
649 * the second bracket */
650 if (ctx
->processor
== TGSI_PROCESSOR_GEOMETRY
&& *file
== TGSI_FILE_INPUT
) {
651 brackets
[0] = brackets
[1];
662 /* Parse destination register operand.*/
665 struct translate_ctx
*ctx
,
667 struct parsed_bracket
*brackets
)
669 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
670 if (!parse_register_file_bracket( ctx
, file
))
672 if (!parse_register_bracket( ctx
, brackets
))
680 struct translate_ctx
*ctx
,
681 struct tgsi_full_dst_register
*dst
)
686 struct parsed_bracket bracket
[2];
687 int parsed_opt_brackets
;
689 if (!parse_register_dst( ctx
, &file
, &bracket
[0] ))
691 if (!parse_opt_register_src_bracket(ctx
, &bracket
[1], &parsed_opt_brackets
))
695 eat_opt_white( &cur
);
697 if (!parse_opt_writemask( ctx
, &writemask
))
700 dst
->Register
.File
= file
;
701 if (parsed_opt_brackets
) {
702 dst
->Register
.Dimension
= 1;
703 dst
->Dimension
.Indirect
= 0;
704 dst
->Dimension
.Dimension
= 0;
705 dst
->Dimension
.Index
= bracket
[0].index
;
706 bracket
[0] = bracket
[1];
708 dst
->Register
.Index
= bracket
[0].index
;
709 dst
->Register
.WriteMask
= writemask
;
710 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
711 dst
->Register
.Indirect
= 1;
712 dst
->Indirect
.File
= bracket
[0].ind_file
;
713 dst
->Indirect
.Index
= bracket
[0].ind_index
;
714 dst
->Indirect
.SwizzleX
= bracket
[0].ind_comp
;
715 dst
->Indirect
.SwizzleY
= bracket
[0].ind_comp
;
716 dst
->Indirect
.SwizzleZ
= bracket
[0].ind_comp
;
717 dst
->Indirect
.SwizzleW
= bracket
[0].ind_comp
;
723 parse_optional_swizzle(
724 struct translate_ctx
*ctx
,
726 boolean
*parsed_swizzle
)
728 const char *cur
= ctx
->cur
;
730 *parsed_swizzle
= FALSE
;
732 eat_opt_white( &cur
);
737 eat_opt_white( &cur
);
738 for (i
= 0; i
< 4; i
++) {
739 if (uprcase( *cur
) == 'X')
740 swizzle
[i
] = TGSI_SWIZZLE_X
;
741 else if (uprcase( *cur
) == 'Y')
742 swizzle
[i
] = TGSI_SWIZZLE_Y
;
743 else if (uprcase( *cur
) == 'Z')
744 swizzle
[i
] = TGSI_SWIZZLE_Z
;
745 else if (uprcase( *cur
) == 'W')
746 swizzle
[i
] = TGSI_SWIZZLE_W
;
748 report_error( ctx
, "Expected register swizzle component `x', `y', `z' or `w'" );
753 *parsed_swizzle
= TRUE
;
761 struct translate_ctx
*ctx
,
762 struct tgsi_full_src_register
*src
)
766 boolean parsed_swizzle
;
767 struct parsed_bracket bracket
[2];
768 int parsed_opt_brackets
;
770 if (*ctx
->cur
== '-') {
772 eat_opt_white( &ctx
->cur
);
773 src
->Register
.Negate
= 1;
776 if (*ctx
->cur
== '|') {
778 eat_opt_white( &ctx
->cur
);
779 src
->Register
.Absolute
= 1;
782 if (!parse_register_src(ctx
, &file
, &bracket
[0]))
784 if (!parse_opt_register_src_bracket(ctx
, &bracket
[1], &parsed_opt_brackets
))
787 src
->Register
.File
= file
;
788 if (parsed_opt_brackets
) {
789 src
->Register
.Dimension
= 1;
790 src
->Dimension
.Indirect
= 0;
791 src
->Dimension
.Dimension
= 0;
792 src
->Dimension
.Index
= bracket
[0].index
;
793 bracket
[0] = bracket
[1];
795 src
->Register
.Index
= bracket
[0].index
;
796 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
797 src
->Register
.Indirect
= 1;
798 src
->Indirect
.File
= bracket
[0].ind_file
;
799 src
->Indirect
.Index
= bracket
[0].ind_index
;
800 src
->Indirect
.SwizzleX
= bracket
[0].ind_comp
;
801 src
->Indirect
.SwizzleY
= bracket
[0].ind_comp
;
802 src
->Indirect
.SwizzleZ
= bracket
[0].ind_comp
;
803 src
->Indirect
.SwizzleW
= bracket
[0].ind_comp
;
806 /* Parse optional swizzle.
808 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
)) {
809 if (parsed_swizzle
) {
810 src
->Register
.SwizzleX
= swizzle
[0];
811 src
->Register
.SwizzleY
= swizzle
[1];
812 src
->Register
.SwizzleZ
= swizzle
[2];
813 src
->Register
.SwizzleW
= swizzle
[3];
817 if (src
->Register
.Absolute
) {
818 eat_opt_white( &ctx
->cur
);
819 if (*ctx
->cur
!= '|') {
820 report_error( ctx
, "Expected `|'" );
831 match_inst(const char **pcur
,
833 const struct tgsi_opcode_info
*info
)
835 const char *cur
= *pcur
;
837 /* simple case: the whole string matches the instruction name */
838 if (str_match_nocase_whole(&cur
, info
->mnemonic
)) {
840 *saturate
= TGSI_SAT_NONE
;
844 if (str_match_no_case(&cur
, info
->mnemonic
)) {
845 /* the instruction has a suffix, figure it out */
846 if (str_match_nocase_whole(&cur
, "_SAT")) {
848 *saturate
= TGSI_SAT_ZERO_ONE
;
852 if (str_match_nocase_whole(&cur
, "_SATNV")) {
854 *saturate
= TGSI_SAT_MINUS_PLUS_ONE
;
864 struct translate_ctx
*ctx
,
868 uint saturate
= TGSI_SAT_NONE
;
869 const struct tgsi_opcode_info
*info
;
870 struct tgsi_full_instruction inst
;
874 inst
= tgsi_default_full_instruction();
878 eat_opt_white( &ctx
->cur
);
879 if (*ctx
->cur
== '(') {
883 boolean parsed_swizzle
;
885 inst
.Instruction
.Predicate
= 1;
888 if (*ctx
->cur
== '!') {
890 inst
.Predicate
.Negate
= 1;
893 if (!parse_register_1d( ctx
, &file
, &index
))
896 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
)) {
897 if (parsed_swizzle
) {
898 inst
.Predicate
.SwizzleX
= swizzle
[0];
899 inst
.Predicate
.SwizzleY
= swizzle
[1];
900 inst
.Predicate
.SwizzleZ
= swizzle
[2];
901 inst
.Predicate
.SwizzleW
= swizzle
[3];
905 if (*ctx
->cur
!= ')') {
906 report_error( ctx
, "Expected `)'" );
913 /* Parse instruction name.
915 eat_opt_white( &ctx
->cur
);
916 for (i
= 0; i
< TGSI_OPCODE_LAST
; i
++) {
919 info
= tgsi_get_opcode_info( i
);
920 if (match_inst(&cur
, &saturate
, info
)) {
921 if (info
->num_dst
+ info
->num_src
+ info
->is_tex
== 0) {
925 else if (*cur
== '\0' || eat_white( &cur
)) {
931 if (i
== TGSI_OPCODE_LAST
) {
933 report_error( ctx
, "Unknown opcode" );
935 report_error( ctx
, "Expected `DCL', `IMM' or a label" );
939 inst
.Instruction
.Opcode
= i
;
940 inst
.Instruction
.Saturate
= saturate
;
941 inst
.Instruction
.NumDstRegs
= info
->num_dst
;
942 inst
.Instruction
.NumSrcRegs
= info
->num_src
;
944 /* Parse instruction operands.
946 for (i
= 0; i
< info
->num_dst
+ info
->num_src
+ info
->is_tex
; i
++) {
948 eat_opt_white( &ctx
->cur
);
949 if (*ctx
->cur
!= ',') {
950 report_error( ctx
, "Expected `,'" );
954 eat_opt_white( &ctx
->cur
);
957 if (i
< info
->num_dst
) {
958 if (!parse_dst_operand( ctx
, &inst
.Dst
[i
] ))
961 else if (i
< info
->num_dst
+ info
->num_src
) {
962 if (!parse_src_operand( ctx
, &inst
.Src
[i
- info
->num_dst
] ))
968 for (j
= 0; j
< TGSI_TEXTURE_COUNT
; j
++) {
969 if (str_match_nocase_whole( &ctx
->cur
, tgsi_texture_names
[j
] )) {
970 inst
.Instruction
.Texture
= 1;
971 inst
.Texture
.Texture
= j
;
975 if (j
== TGSI_TEXTURE_COUNT
) {
976 report_error( ctx
, "Expected texture target" );
983 eat_opt_white( &cur
);
984 if (info
->is_branch
&& *cur
== ':') {
988 eat_opt_white( &cur
);
989 if (!parse_uint( &cur
, &target
)) {
990 report_error( ctx
, "Expected a label" );
993 inst
.Instruction
.Label
= 1;
994 inst
.Label
.Label
= target
;
998 advance
= tgsi_build_full_instruction(
1002 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1005 ctx
->tokens_cur
+= advance
;
1010 /* parses a 4-touple of the form {x, y, z, w}
1011 * where x, y, z, w are numbers */
1012 static boolean
parse_immediate_data(struct translate_ctx
*ctx
, unsigned type
,
1013 union tgsi_immediate_data
*values
)
1018 eat_opt_white( &ctx
->cur
);
1019 if (*ctx
->cur
!= '{') {
1020 report_error( ctx
, "Expected `{'" );
1024 for (i
= 0; i
< 4; i
++) {
1025 eat_opt_white( &ctx
->cur
);
1027 if (*ctx
->cur
!= ',') {
1028 report_error( ctx
, "Expected `,'" );
1032 eat_opt_white( &ctx
->cur
);
1036 case TGSI_IMM_FLOAT32
:
1037 ret
= parse_float(&ctx
->cur
, &values
[i
].Float
);
1039 case TGSI_IMM_UINT32
:
1040 ret
= parse_uint(&ctx
->cur
, &values
[i
].Uint
);
1042 case TGSI_IMM_INT32
:
1043 ret
= parse_int(&ctx
->cur
, &values
[i
].Int
);
1052 report_error( ctx
, "Expected immediate constant" );
1056 eat_opt_white( &ctx
->cur
);
1057 if (*ctx
->cur
!= '}') {
1058 report_error( ctx
, "Expected `}'" );
1066 static boolean
parse_declaration( struct translate_ctx
*ctx
)
1068 struct tgsi_full_declaration decl
;
1070 struct parsed_dcl_bracket brackets
[2];
1073 const char *cur
, *cur2
;
1075 boolean is_vs_input
;
1076 boolean is_imm_array
;
1078 if (!eat_white( &ctx
->cur
)) {
1079 report_error( ctx
, "Syntax error" );
1082 if (!parse_register_dcl( ctx
, &file
, brackets
, &num_brackets
))
1084 if (!parse_opt_writemask( ctx
, &writemask
))
1087 decl
= tgsi_default_full_declaration();
1088 decl
.Declaration
.File
= file
;
1089 decl
.Declaration
.UsageMask
= writemask
;
1091 if (num_brackets
== 1) {
1092 decl
.Range
.First
= brackets
[0].first
;
1093 decl
.Range
.Last
= brackets
[0].last
;
1095 decl
.Range
.First
= brackets
[1].first
;
1096 decl
.Range
.Last
= brackets
[1].last
;
1098 decl
.Declaration
.Dimension
= 1;
1099 decl
.Dim
.Index2D
= brackets
[0].first
;
1102 is_vs_input
= (file
== TGSI_FILE_INPUT
&&
1103 ctx
->processor
== TGSI_PROCESSOR_VERTEX
);
1104 is_imm_array
= (file
== TGSI_FILE_IMMEDIATE_ARRAY
);
1107 eat_opt_white( &cur
);
1108 if (*cur
== ',' && !is_vs_input
) {
1112 eat_opt_white( &cur
);
1113 if (file
== TGSI_FILE_RESOURCE
) {
1114 for (i
= 0; i
< TGSI_TEXTURE_COUNT
; i
++) {
1115 if (str_match_nocase_whole(&cur
, tgsi_texture_names
[i
])) {
1116 decl
.Resource
.Resource
= i
;
1120 if (i
== TGSI_TEXTURE_COUNT
) {
1121 report_error(ctx
, "Expected texture target");
1126 eat_opt_white(&cur2
);
1127 while (*cur2
== ',') {
1129 eat_opt_white(&cur2
);
1130 if (str_match_nocase_whole(&cur2
, "RAW")) {
1131 decl
.Resource
.Raw
= 1;
1133 } else if (str_match_nocase_whole(&cur2
, "WR")) {
1134 decl
.Resource
.Writable
= 1;
1140 eat_opt_white(&cur2
);
1145 } else if (file
== TGSI_FILE_SAMPLER_VIEW
) {
1146 for (i
= 0; i
< TGSI_TEXTURE_COUNT
; i
++) {
1147 if (str_match_nocase_whole(&cur
, tgsi_texture_names
[i
])) {
1148 decl
.SamplerView
.Resource
= i
;
1152 if (i
== TGSI_TEXTURE_COUNT
) {
1153 report_error(ctx
, "Expected texture target");
1156 eat_opt_white( &cur
);
1158 report_error( ctx
, "Expected `,'" );
1162 eat_opt_white( &cur
);
1163 for (j
= 0; j
< 4; ++j
) {
1164 for (i
= 0; i
< PIPE_TYPE_COUNT
; ++i
) {
1165 if (str_match_nocase_whole(&cur
, tgsi_type_names
[i
])) {
1168 decl
.SamplerView
.ReturnTypeX
= i
;
1171 decl
.SamplerView
.ReturnTypeY
= i
;
1174 decl
.SamplerView
.ReturnTypeZ
= i
;
1177 decl
.SamplerView
.ReturnTypeW
= i
;
1185 if (i
== PIPE_TYPE_COUNT
) {
1186 if (j
== 0 || j
> 2) {
1187 report_error(ctx
, "Expected type name");
1193 eat_opt_white( &cur2
);
1196 eat_opt_white( &cur2
);
1204 decl
.SamplerView
.ReturnTypeY
=
1205 decl
.SamplerView
.ReturnTypeZ
=
1206 decl
.SamplerView
.ReturnTypeW
=
1207 decl
.SamplerView
.ReturnTypeX
;
1211 if (str_match_nocase_whole(&cur
, "LOCAL")) {
1212 decl
.Declaration
.Local
= 1;
1217 eat_opt_white( &cur
);
1220 eat_opt_white( &cur
);
1222 for (i
= 0; i
< TGSI_SEMANTIC_COUNT
; i
++) {
1223 if (str_match_nocase_whole(&cur
, tgsi_semantic_names
[i
])) {
1227 eat_opt_white( &cur2
);
1230 eat_opt_white( &cur2
);
1231 if (!parse_uint( &cur2
, &index
)) {
1232 report_error( ctx
, "Expected literal integer" );
1235 eat_opt_white( &cur2
);
1237 report_error( ctx
, "Expected `]'" );
1242 decl
.Semantic
.Index
= index
;
1247 decl
.Declaration
.Semantic
= 1;
1248 decl
.Semantic
.Name
= i
;
1256 } else if (is_imm_array
) {
1258 union tgsi_immediate_data
*vals_itr
;
1259 /* we have our immediate data */
1261 report_error( ctx
, "Immediate array without data" );
1267 decl
.ImmediateData
.u
=
1268 MALLOC(sizeof(union tgsi_immediate_data
) * 4 *
1269 (decl
.Range
.Last
+ 1));
1270 vals_itr
= decl
.ImmediateData
.u
;
1271 for (i
= 0; i
<= decl
.Range
.Last
; ++i
) {
1272 if (!parse_immediate_data(ctx
, TGSI_IMM_FLOAT32
, vals_itr
)) {
1273 FREE(decl
.ImmediateData
.u
);
1277 eat_opt_white( &ctx
->cur
);
1278 if (*ctx
->cur
!= ',') {
1279 if (i
!= decl
.Range
.Last
) {
1280 report_error( ctx
, "Not enough data in immediate array!" );
1281 FREE(decl
.ImmediateData
.u
);
1287 eat_opt_white( &ctx
->cur
);
1288 if (*ctx
->cur
!= '}') {
1289 FREE(decl
.ImmediateData
.u
);
1290 report_error( ctx
, "Immediate array data missing closing '}'" );
1297 eat_opt_white( &cur
);
1298 if (*cur
== ',' && !is_vs_input
) {
1302 eat_opt_white( &cur
);
1303 for (i
= 0; i
< TGSI_INTERPOLATE_COUNT
; i
++) {
1304 if (str_match_nocase_whole( &cur
, tgsi_interpolate_names
[i
] )) {
1305 decl
.Declaration
.Interpolate
= 1;
1306 decl
.Interp
.Interpolate
= i
;
1312 if (i
== TGSI_INTERPOLATE_COUNT
) {
1313 report_error( ctx
, "Expected semantic or interpolate attribute" );
1318 advance
= tgsi_build_full_declaration(
1322 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1325 FREE(decl
.ImmediateData
.u
);
1329 ctx
->tokens_cur
+= advance
;
1334 static boolean
parse_immediate( struct translate_ctx
*ctx
)
1336 struct tgsi_full_immediate imm
;
1340 if (*ctx
->cur
== '[') {
1345 eat_opt_white( &ctx
->cur
);
1346 if (!parse_uint( &ctx
->cur
, &uindex
)) {
1347 report_error( ctx
, "Expected literal unsigned integer" );
1351 if (uindex
!= ctx
->num_immediates
) {
1352 report_error( ctx
, "Immediates must be sorted" );
1356 eat_opt_white( &ctx
->cur
);
1357 if (*ctx
->cur
!= ']') {
1358 report_error( ctx
, "Expected `]'" );
1365 if (!eat_white( &ctx
->cur
)) {
1366 report_error( ctx
, "Syntax error" );
1369 for (type
= 0; type
< Elements(tgsi_immediate_type_names
); ++type
) {
1370 if (str_match_nocase_whole(&ctx
->cur
, tgsi_immediate_type_names
[type
]))
1373 if (type
== Elements(tgsi_immediate_type_names
)) {
1374 report_error( ctx
, "Expected immediate type" );
1378 imm
= tgsi_default_full_immediate();
1379 imm
.Immediate
.NrTokens
+= 4;
1380 imm
.Immediate
.DataType
= type
;
1381 parse_immediate_data(ctx
, type
, imm
.u
);
1383 advance
= tgsi_build_full_immediate(
1387 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1390 ctx
->tokens_cur
+= advance
;
1392 ctx
->num_immediates
++;
1398 parse_primitive( const char **pcur
, uint
*primitive
)
1402 for (i
= 0; i
< PIPE_PRIM_MAX
; i
++) {
1403 const char *cur
= *pcur
;
1405 if (str_match_nocase_whole( &cur
, tgsi_primitive_names
[i
])) {
1415 parse_fs_coord_origin( const char **pcur
, uint
*fs_coord_origin
)
1419 for (i
= 0; i
< Elements(tgsi_fs_coord_origin_names
); i
++) {
1420 const char *cur
= *pcur
;
1422 if (str_match_nocase_whole( &cur
, tgsi_fs_coord_origin_names
[i
])) {
1423 *fs_coord_origin
= i
;
1432 parse_fs_coord_pixel_center( const char **pcur
, uint
*fs_coord_pixel_center
)
1436 for (i
= 0; i
< Elements(tgsi_fs_coord_pixel_center_names
); i
++) {
1437 const char *cur
= *pcur
;
1439 if (str_match_nocase_whole( &cur
, tgsi_fs_coord_pixel_center_names
[i
])) {
1440 *fs_coord_pixel_center
= i
;
1449 static boolean
parse_property( struct translate_ctx
*ctx
)
1451 struct tgsi_full_property prop
;
1457 if (!eat_white( &ctx
->cur
)) {
1458 report_error( ctx
, "Syntax error" );
1461 if (!parse_identifier( &ctx
->cur
, id
)) {
1462 report_error( ctx
, "Syntax error" );
1465 for (property_name
= 0; property_name
< TGSI_PROPERTY_COUNT
;
1467 if (streq_nocase_uprcase(tgsi_property_names
[property_name
], id
)) {
1471 if (property_name
>= TGSI_PROPERTY_COUNT
) {
1472 debug_printf( "\nError: Unknown property : '%s'", id
);
1476 eat_opt_white( &ctx
->cur
);
1477 switch(property_name
) {
1478 case TGSI_PROPERTY_GS_INPUT_PRIM
:
1479 case TGSI_PROPERTY_GS_OUTPUT_PRIM
:
1480 if (!parse_primitive(&ctx
->cur
, &values
[0] )) {
1481 report_error( ctx
, "Unknown primitive name as property!" );
1484 if (property_name
== TGSI_PROPERTY_GS_INPUT_PRIM
&&
1485 ctx
->processor
== TGSI_PROCESSOR_GEOMETRY
) {
1486 ctx
->implied_array_size
= u_vertices_per_prim(values
[0]);
1489 case TGSI_PROPERTY_FS_COORD_ORIGIN
:
1490 if (!parse_fs_coord_origin(&ctx
->cur
, &values
[0] )) {
1491 report_error( ctx
, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1495 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER
:
1496 if (!parse_fs_coord_pixel_center(&ctx
->cur
, &values
[0] )) {
1497 report_error( ctx
, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1501 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS
:
1503 if (!parse_uint(&ctx
->cur
, &values
[0] )) {
1504 report_error( ctx
, "Expected unsigned integer as property!" );
1509 prop
= tgsi_default_full_property();
1510 prop
.Property
.PropertyName
= property_name
;
1511 prop
.Property
.NrTokens
+= 1;
1512 prop
.u
[0].Data
= values
[0];
1514 advance
= tgsi_build_full_property(
1518 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1521 ctx
->tokens_cur
+= advance
;
1527 static boolean
translate( struct translate_ctx
*ctx
)
1529 eat_opt_white( &ctx
->cur
);
1530 if (!parse_header( ctx
))
1533 while (*ctx
->cur
!= '\0') {
1535 if (!eat_white( &ctx
->cur
)) {
1536 report_error( ctx
, "Syntax error" );
1540 if (*ctx
->cur
== '\0')
1542 if (parse_label( ctx
, &label_val
)) {
1543 if (!parse_instruction( ctx
, TRUE
))
1546 else if (str_match_nocase_whole( &ctx
->cur
, "DCL" )) {
1547 if (!parse_declaration( ctx
))
1550 else if (str_match_nocase_whole( &ctx
->cur
, "IMM" )) {
1551 if (!parse_immediate( ctx
))
1554 else if (str_match_nocase_whole( &ctx
->cur
, "PROPERTY" )) {
1555 if (!parse_property( ctx
))
1558 else if (!parse_instruction( ctx
, FALSE
)) {
1567 tgsi_text_translate(
1569 struct tgsi_token
*tokens
,
1572 struct translate_ctx ctx
;
1576 ctx
.tokens
= tokens
;
1577 ctx
.tokens_cur
= tokens
;
1578 ctx
.tokens_end
= tokens
+ num_tokens
;
1580 if (!translate( &ctx
))
1583 return tgsi_sanity_check( tokens
);