1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
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 VMWARE 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 /* Return the array index that matches starting at *pcur, where the string at
123 * *pcur is terminated by a non-digit non-letter non-underscore.
124 * Returns -1 if no match is found.
126 * On success, the pointer to the first string is moved to the end of the read
129 static int str_match_name_from_array(const char **pcur
,
130 const char * const *array
,
133 for (unsigned j
= 0; j
< array_size
; ++j
) {
134 if (str_match_nocase_whole(pcur
, array
[j
]))
140 /* Return the format corresponding to the name at *pcur.
141 * Returns -1 if there is no format name.
143 * On success, the pointer to the string is moved to the end of the read format
146 static int str_match_format(const char **pcur
)
148 for (unsigned i
= 0; i
< PIPE_FORMAT_COUNT
; i
++) {
149 const struct util_format_description
*desc
=
150 util_format_description(i
);
151 if (desc
&& str_match_nocase_whole(pcur
, desc
->name
)) {
158 /* Eat zero or more whitespaces.
160 static void eat_opt_white( const char **pcur
)
162 while (**pcur
== ' ' || **pcur
== '\t' || **pcur
== '\n')
166 /* Eat one or more whitespaces.
167 * Return TRUE if at least one whitespace eaten.
169 static boolean
eat_white( const char **pcur
)
171 const char *cur
= *pcur
;
173 eat_opt_white( pcur
);
177 /* Parse unsigned integer.
178 * No checks for overflow.
180 static boolean
parse_uint( const char **pcur
, uint
*val
)
182 const char *cur
= *pcur
;
184 if (is_digit( cur
)) {
186 while (is_digit( cur
))
187 *val
= *val
* 10 + *cur
++ - '0';
194 static boolean
parse_int( const char **pcur
, int *val
)
196 const char *cur
= *pcur
;
197 int sign
= (*cur
== '-' ? -1 : 1);
199 if (*cur
== '+' || *cur
== '-')
202 if (parse_uint(&cur
, (uint
*)val
)) {
211 static boolean
parse_identifier( const char **pcur
, char *ret
, size_t len
)
213 const char *cur
= *pcur
;
215 if (is_alpha_underscore( cur
)) {
217 while (is_alpha_underscore( cur
) || is_digit( cur
)) {
229 /* Parse floating point.
231 static boolean
parse_float( const char **pcur
, float *val
)
233 const char *cur
= *pcur
;
234 boolean integral_part
= FALSE
;
235 boolean fractional_part
= FALSE
;
237 if (*cur
== '0' && *(cur
+ 1) == 'x') {
239 fi
.ui
= strtoul(cur
, NULL
, 16);
245 *val
= (float) atof( cur
);
246 if (*cur
== '-' || *cur
== '+')
248 if (is_digit( cur
)) {
250 integral_part
= TRUE
;
251 while (is_digit( cur
))
256 if (is_digit( cur
)) {
258 fractional_part
= TRUE
;
259 while (is_digit( cur
))
263 if (!integral_part
&& !fractional_part
)
265 if (uprcase( *cur
) == 'E') {
267 if (*cur
== '-' || *cur
== '+')
269 if (is_digit( cur
)) {
271 while (is_digit( cur
))
283 static boolean
parse_double( const char **pcur
, uint32_t *val0
, uint32_t *val1
)
285 const char *cur
= *pcur
;
291 v
.dval
= strtod(cur
, (char**)pcur
);
301 static boolean
parse_int64( const char **pcur
, uint32_t *val0
, uint32_t *val1
)
303 const char *cur
= *pcur
;
309 v
.i64val
= strtoll(cur
, (char**)pcur
, 0);
319 static boolean
parse_uint64( const char **pcur
, uint32_t *val0
, uint32_t *val1
)
321 const char *cur
= *pcur
;
327 v
.u64val
= strtoull(cur
, (char**)pcur
, 0);
341 struct tgsi_token
*tokens
;
342 struct tgsi_token
*tokens_cur
;
343 struct tgsi_token
*tokens_end
;
344 struct tgsi_header
*header
;
345 unsigned processor
: 4;
346 unsigned implied_array_size
: 6;
347 unsigned num_immediates
;
350 static void report_error( struct translate_ctx
*ctx
, const char *msg
)
354 const char *itr
= ctx
->text
;
356 while (itr
!= ctx
->cur
) {
365 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg
, line
, column
);
368 /* Parse shader header.
369 * Return TRUE for one of the following headers.
374 static boolean
parse_header( struct translate_ctx
*ctx
)
378 if (str_match_nocase_whole( &ctx
->cur
, "FRAG" ))
379 processor
= PIPE_SHADER_FRAGMENT
;
380 else if (str_match_nocase_whole( &ctx
->cur
, "VERT" ))
381 processor
= PIPE_SHADER_VERTEX
;
382 else if (str_match_nocase_whole( &ctx
->cur
, "GEOM" ))
383 processor
= PIPE_SHADER_GEOMETRY
;
384 else if (str_match_nocase_whole( &ctx
->cur
, "TESS_CTRL" ))
385 processor
= PIPE_SHADER_TESS_CTRL
;
386 else if (str_match_nocase_whole( &ctx
->cur
, "TESS_EVAL" ))
387 processor
= PIPE_SHADER_TESS_EVAL
;
388 else if (str_match_nocase_whole( &ctx
->cur
, "COMP" ))
389 processor
= PIPE_SHADER_COMPUTE
;
391 report_error( ctx
, "Unknown header" );
395 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
397 ctx
->header
= (struct tgsi_header
*) ctx
->tokens_cur
++;
398 *ctx
->header
= tgsi_build_header();
400 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
402 *(struct tgsi_processor
*) ctx
->tokens_cur
++ = tgsi_build_processor( processor
, ctx
->header
);
403 ctx
->processor
= processor
;
408 static boolean
parse_label( struct translate_ctx
*ctx
, uint
*val
)
410 const char *cur
= ctx
->cur
;
412 if (parse_uint( &cur
, val
)) {
413 eat_opt_white( &cur
);
424 parse_file( const char **pcur
, uint
*file
)
428 for (i
= 0; i
< TGSI_FILE_COUNT
; i
++) {
429 const char *cur
= *pcur
;
431 if (str_match_nocase_whole( &cur
, tgsi_file_name(i
) )) {
442 struct translate_ctx
*ctx
,
448 eat_opt_white( &cur
);
451 *writemask
= TGSI_WRITEMASK_NONE
;
452 eat_opt_white( &cur
);
453 if (uprcase( *cur
) == 'X') {
455 *writemask
|= TGSI_WRITEMASK_X
;
457 if (uprcase( *cur
) == 'Y') {
459 *writemask
|= TGSI_WRITEMASK_Y
;
461 if (uprcase( *cur
) == 'Z') {
463 *writemask
|= TGSI_WRITEMASK_Z
;
465 if (uprcase( *cur
) == 'W') {
467 *writemask
|= TGSI_WRITEMASK_W
;
470 if (*writemask
== TGSI_WRITEMASK_NONE
) {
471 report_error( ctx
, "Writemask expected" );
478 *writemask
= TGSI_WRITEMASK_XYZW
;
484 /* <register_file_bracket> ::= <file> `['
487 parse_register_file_bracket(
488 struct translate_ctx
*ctx
,
491 if (!parse_file( &ctx
->cur
, file
)) {
492 report_error( ctx
, "Unknown register file" );
495 eat_opt_white( &ctx
->cur
);
496 if (*ctx
->cur
!= '[') {
497 report_error( ctx
, "Expected `['" );
504 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
507 parse_register_file_bracket_index(
508 struct translate_ctx
*ctx
,
514 if (!parse_register_file_bracket( ctx
, file
))
516 eat_opt_white( &ctx
->cur
);
517 if (!parse_uint( &ctx
->cur
, &uindex
)) {
518 report_error( ctx
, "Expected literal unsigned integer" );
521 *index
= (int) uindex
;
525 /* Parse simple 1d register operand.
526 * <register_dst> ::= <register_file_bracket_index> `]'
529 parse_register_1d(struct translate_ctx
*ctx
,
533 if (!parse_register_file_bracket_index( ctx
, file
, index
))
535 eat_opt_white( &ctx
->cur
);
536 if (*ctx
->cur
!= ']') {
537 report_error( ctx
, "Expected `]'" );
544 struct parsed_bracket
{
555 parse_register_bracket(
556 struct translate_ctx
*ctx
,
557 struct parsed_bracket
*brackets
)
562 memset(brackets
, 0, sizeof(struct parsed_bracket
));
564 eat_opt_white( &ctx
->cur
);
567 if (parse_file( &cur
, &brackets
->ind_file
)) {
568 if (!parse_register_1d( ctx
, &brackets
->ind_file
,
569 &brackets
->ind_index
))
571 eat_opt_white( &ctx
->cur
);
573 if (*ctx
->cur
== '.') {
575 eat_opt_white(&ctx
->cur
);
577 switch (uprcase(*ctx
->cur
)) {
579 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
582 brackets
->ind_comp
= TGSI_SWIZZLE_Y
;
585 brackets
->ind_comp
= TGSI_SWIZZLE_Z
;
588 brackets
->ind_comp
= TGSI_SWIZZLE_W
;
591 report_error(ctx
, "Expected indirect register swizzle component `x', `y', `z' or `w'");
595 eat_opt_white(&ctx
->cur
);
598 if (*ctx
->cur
== '+' || *ctx
->cur
== '-')
599 parse_int( &ctx
->cur
, &brackets
->index
);
604 if (!parse_uint( &ctx
->cur
, &uindex
)) {
605 report_error( ctx
, "Expected literal unsigned integer" );
608 brackets
->index
= (int) uindex
;
609 brackets
->ind_file
= TGSI_FILE_NULL
;
610 brackets
->ind_index
= 0;
612 eat_opt_white( &ctx
->cur
);
613 if (*ctx
->cur
!= ']') {
614 report_error( ctx
, "Expected `]'" );
618 if (*ctx
->cur
== '(') {
620 eat_opt_white( &ctx
->cur
);
621 if (!parse_uint( &ctx
->cur
, &brackets
->ind_array
)) {
622 report_error( ctx
, "Expected literal unsigned integer" );
625 eat_opt_white( &ctx
->cur
);
626 if (*ctx
->cur
!= ')') {
627 report_error( ctx
, "Expected `)'" );
636 parse_opt_register_src_bracket(
637 struct translate_ctx
*ctx
,
638 struct parsed_bracket
*brackets
,
639 int *parsed_brackets
)
641 const char *cur
= ctx
->cur
;
643 *parsed_brackets
= 0;
645 eat_opt_white( &cur
);
650 if (!parse_register_bracket(ctx
, brackets
))
653 *parsed_brackets
= 1;
660 /* Parse source register operand.
661 * <register_src> ::= <register_file_bracket_index> `]' |
662 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
663 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
664 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
668 struct translate_ctx
*ctx
,
670 struct parsed_bracket
*brackets
)
672 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
673 if (!parse_register_file_bracket( ctx
, file
))
675 if (!parse_register_bracket( ctx
, brackets
))
681 struct parsed_dcl_bracket
{
687 parse_register_dcl_bracket(
688 struct translate_ctx
*ctx
,
689 struct parsed_dcl_bracket
*bracket
)
692 memset(bracket
, 0, sizeof(struct parsed_dcl_bracket
));
694 eat_opt_white( &ctx
->cur
);
696 if (!parse_uint( &ctx
->cur
, &uindex
)) {
697 /* it can be an empty bracket [] which means its range
698 * is from 0 to some implied size */
699 if (ctx
->cur
[0] == ']' && ctx
->implied_array_size
!= 0) {
701 bracket
->last
= ctx
->implied_array_size
- 1;
704 report_error( ctx
, "Expected literal unsigned integer" );
707 bracket
->first
= uindex
;
709 eat_opt_white( &ctx
->cur
);
711 if (ctx
->cur
[0] == '.' && ctx
->cur
[1] == '.') {
715 eat_opt_white( &ctx
->cur
);
716 if (!parse_uint( &ctx
->cur
, &uindex
)) {
717 report_error( ctx
, "Expected literal integer" );
720 bracket
->last
= (int) uindex
;
721 eat_opt_white( &ctx
->cur
);
724 bracket
->last
= bracket
->first
;
728 if (*ctx
->cur
!= ']') {
729 report_error( ctx
, "Expected `]' or `..'" );
736 /* Parse register declaration.
737 * <register_dcl> ::= <register_file_bracket_index> `]' |
738 * <register_file_bracket_index> `..' <index> `]'
742 struct translate_ctx
*ctx
,
744 struct parsed_dcl_bracket
*brackets
,
751 if (!parse_register_file_bracket( ctx
, file
))
753 if (!parse_register_dcl_bracket( ctx
, &brackets
[0] ))
759 eat_opt_white( &cur
);
762 bool is_in
= *file
== TGSI_FILE_INPUT
;
763 bool is_out
= *file
== TGSI_FILE_OUTPUT
;
767 if (!parse_register_dcl_bracket( ctx
, &brackets
[1] ))
769 /* for geometry shader we don't really care about
770 * the first brackets it's always the size of the
771 * input primitive. so we want to declare just
772 * the index relevant to the semantics which is in
773 * the second bracket */
775 /* tessellation has similar constraints to geometry shader */
776 if ((ctx
->processor
== PIPE_SHADER_GEOMETRY
&& is_in
) ||
777 (ctx
->processor
== PIPE_SHADER_TESS_EVAL
&& is_in
) ||
778 (ctx
->processor
== PIPE_SHADER_TESS_CTRL
&& (is_in
|| is_out
))) {
779 brackets
[0] = brackets
[1];
790 /* Parse destination register operand.*/
793 struct translate_ctx
*ctx
,
795 struct parsed_bracket
*brackets
)
797 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
798 if (!parse_register_file_bracket( ctx
, file
))
800 if (!parse_register_bracket( ctx
, brackets
))
808 struct translate_ctx
*ctx
,
809 struct tgsi_full_dst_register
*dst
)
814 struct parsed_bracket bracket
[2];
815 int parsed_opt_brackets
;
817 if (!parse_register_dst( ctx
, &file
, &bracket
[0] ))
819 if (!parse_opt_register_src_bracket(ctx
, &bracket
[1], &parsed_opt_brackets
))
823 eat_opt_white( &cur
);
825 if (!parse_opt_writemask( ctx
, &writemask
))
828 dst
->Register
.File
= file
;
829 if (parsed_opt_brackets
) {
830 dst
->Register
.Dimension
= 1;
831 dst
->Dimension
.Indirect
= 0;
832 dst
->Dimension
.Dimension
= 0;
833 dst
->Dimension
.Index
= bracket
[0].index
;
835 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
836 dst
->Dimension
.Indirect
= 1;
837 dst
->DimIndirect
.File
= bracket
[0].ind_file
;
838 dst
->DimIndirect
.Index
= bracket
[0].ind_index
;
839 dst
->DimIndirect
.Swizzle
= bracket
[0].ind_comp
;
840 dst
->DimIndirect
.ArrayID
= bracket
[0].ind_array
;
842 bracket
[0] = bracket
[1];
844 dst
->Register
.Index
= bracket
[0].index
;
845 dst
->Register
.WriteMask
= writemask
;
846 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
847 dst
->Register
.Indirect
= 1;
848 dst
->Indirect
.File
= bracket
[0].ind_file
;
849 dst
->Indirect
.Index
= bracket
[0].ind_index
;
850 dst
->Indirect
.Swizzle
= bracket
[0].ind_comp
;
851 dst
->Indirect
.ArrayID
= bracket
[0].ind_array
;
857 parse_optional_swizzle(
858 struct translate_ctx
*ctx
,
860 boolean
*parsed_swizzle
,
863 const char *cur
= ctx
->cur
;
865 *parsed_swizzle
= FALSE
;
867 eat_opt_white( &cur
);
872 eat_opt_white( &cur
);
873 for (i
= 0; i
< components
; i
++) {
874 if (uprcase( *cur
) == 'X')
875 swizzle
[i
] = TGSI_SWIZZLE_X
;
876 else if (uprcase( *cur
) == 'Y')
877 swizzle
[i
] = TGSI_SWIZZLE_Y
;
878 else if (uprcase( *cur
) == 'Z')
879 swizzle
[i
] = TGSI_SWIZZLE_Z
;
880 else if (uprcase( *cur
) == 'W')
881 swizzle
[i
] = TGSI_SWIZZLE_W
;
883 report_error( ctx
, "Expected register swizzle component `x', `y', `z' or `w'" );
888 *parsed_swizzle
= TRUE
;
896 struct translate_ctx
*ctx
,
897 struct tgsi_full_src_register
*src
)
901 boolean parsed_swizzle
;
902 struct parsed_bracket bracket
[2];
903 int parsed_opt_brackets
;
905 if (*ctx
->cur
== '-') {
907 eat_opt_white( &ctx
->cur
);
908 src
->Register
.Negate
= 1;
911 if (*ctx
->cur
== '|') {
913 eat_opt_white( &ctx
->cur
);
914 src
->Register
.Absolute
= 1;
917 if (!parse_register_src(ctx
, &file
, &bracket
[0]))
919 if (!parse_opt_register_src_bracket(ctx
, &bracket
[1], &parsed_opt_brackets
))
922 src
->Register
.File
= file
;
923 if (parsed_opt_brackets
) {
924 src
->Register
.Dimension
= 1;
925 src
->Dimension
.Indirect
= 0;
926 src
->Dimension
.Dimension
= 0;
927 src
->Dimension
.Index
= bracket
[0].index
;
928 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
929 src
->Dimension
.Indirect
= 1;
930 src
->DimIndirect
.File
= bracket
[0].ind_file
;
931 src
->DimIndirect
.Index
= bracket
[0].ind_index
;
932 src
->DimIndirect
.Swizzle
= bracket
[0].ind_comp
;
933 src
->DimIndirect
.ArrayID
= bracket
[0].ind_array
;
935 bracket
[0] = bracket
[1];
937 src
->Register
.Index
= bracket
[0].index
;
938 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
939 src
->Register
.Indirect
= 1;
940 src
->Indirect
.File
= bracket
[0].ind_file
;
941 src
->Indirect
.Index
= bracket
[0].ind_index
;
942 src
->Indirect
.Swizzle
= bracket
[0].ind_comp
;
943 src
->Indirect
.ArrayID
= bracket
[0].ind_array
;
946 /* Parse optional swizzle.
948 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
, 4 )) {
949 if (parsed_swizzle
) {
950 src
->Register
.SwizzleX
= swizzle
[0];
951 src
->Register
.SwizzleY
= swizzle
[1];
952 src
->Register
.SwizzleZ
= swizzle
[2];
953 src
->Register
.SwizzleW
= swizzle
[3];
957 if (src
->Register
.Absolute
) {
958 eat_opt_white( &ctx
->cur
);
959 if (*ctx
->cur
!= '|') {
960 report_error( ctx
, "Expected `|'" );
971 parse_texoffset_operand(
972 struct translate_ctx
*ctx
,
973 struct tgsi_texture_offset
*src
)
977 boolean parsed_swizzle
;
978 struct parsed_bracket bracket
;
980 if (!parse_register_src(ctx
, &file
, &bracket
))
984 src
->Index
= bracket
.index
;
986 /* Parse optional swizzle.
988 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
, 3 )) {
989 if (parsed_swizzle
) {
990 src
->SwizzleX
= swizzle
[0];
991 src
->SwizzleY
= swizzle
[1];
992 src
->SwizzleZ
= swizzle
[2];
1000 match_inst(const char **pcur
,
1002 const struct tgsi_opcode_info
*info
)
1004 const char *cur
= *pcur
;
1006 /* simple case: the whole string matches the instruction name */
1007 if (str_match_nocase_whole(&cur
, info
->mnemonic
)) {
1013 if (str_match_no_case(&cur
, info
->mnemonic
)) {
1014 /* the instruction has a suffix, figure it out */
1015 if (str_match_nocase_whole(&cur
, "_SAT")) {
1027 struct translate_ctx
*ctx
,
1032 const struct tgsi_opcode_info
*info
;
1033 struct tgsi_full_instruction inst
;
1037 inst
= tgsi_default_full_instruction();
1041 eat_opt_white( &ctx
->cur
);
1042 if (*ctx
->cur
== '(') {
1046 boolean parsed_swizzle
;
1048 inst
.Instruction
.Predicate
= 1;
1051 if (*ctx
->cur
== '!') {
1053 inst
.Predicate
.Negate
= 1;
1056 if (!parse_register_1d( ctx
, &file
, &index
))
1059 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
, 4 )) {
1060 if (parsed_swizzle
) {
1061 inst
.Predicate
.SwizzleX
= swizzle
[0];
1062 inst
.Predicate
.SwizzleY
= swizzle
[1];
1063 inst
.Predicate
.SwizzleZ
= swizzle
[2];
1064 inst
.Predicate
.SwizzleW
= swizzle
[3];
1068 if (*ctx
->cur
!= ')') {
1069 report_error( ctx
, "Expected `)'" );
1076 /* Parse instruction name.
1078 eat_opt_white( &ctx
->cur
);
1079 for (i
= 0; i
< TGSI_OPCODE_LAST
; i
++) {
1082 info
= tgsi_get_opcode_info( i
);
1083 if (match_inst(&cur
, &saturate
, info
)) {
1084 if (info
->num_dst
+ info
->num_src
+ info
->is_tex
== 0) {
1088 else if (*cur
== '\0' || eat_white( &cur
)) {
1094 if (i
== TGSI_OPCODE_LAST
) {
1096 report_error( ctx
, "Unknown opcode" );
1098 report_error( ctx
, "Expected `DCL', `IMM' or a label" );
1102 inst
.Instruction
.Opcode
= i
;
1103 inst
.Instruction
.Saturate
= saturate
;
1104 inst
.Instruction
.NumDstRegs
= info
->num_dst
;
1105 inst
.Instruction
.NumSrcRegs
= info
->num_src
;
1107 if (i
>= TGSI_OPCODE_SAMPLE
&& i
<= TGSI_OPCODE_GATHER4
) {
1109 * These are not considered tex opcodes here (no additional
1110 * target argument) however we're required to set the Texture
1111 * bit so we can set the number of tex offsets.
1113 inst
.Instruction
.Texture
= 1;
1114 inst
.Texture
.Texture
= TGSI_TEXTURE_UNKNOWN
;
1117 if ((i
>= TGSI_OPCODE_LOAD
&& i
<= TGSI_OPCODE_ATOMIMAX
) ||
1118 i
== TGSI_OPCODE_RESQ
) {
1119 inst
.Instruction
.Memory
= 1;
1120 inst
.Memory
.Qualifier
= 0;
1123 assume(info
->num_dst
<= TGSI_FULL_MAX_DST_REGISTERS
);
1124 assume(info
->num_src
<= TGSI_FULL_MAX_SRC_REGISTERS
);
1126 /* Parse instruction operands.
1128 for (i
= 0; i
< info
->num_dst
+ info
->num_src
+ info
->is_tex
; i
++) {
1130 eat_opt_white( &ctx
->cur
);
1131 if (*ctx
->cur
!= ',') {
1132 report_error( ctx
, "Expected `,'" );
1136 eat_opt_white( &ctx
->cur
);
1139 if (i
< info
->num_dst
) {
1140 if (!parse_dst_operand( ctx
, &inst
.Dst
[i
] ))
1143 else if (i
< info
->num_dst
+ info
->num_src
) {
1144 if (!parse_src_operand( ctx
, &inst
.Src
[i
- info
->num_dst
] ))
1150 for (j
= 0; j
< TGSI_TEXTURE_COUNT
; j
++) {
1151 if (str_match_nocase_whole( &ctx
->cur
, tgsi_texture_names
[j
] )) {
1152 inst
.Instruction
.Texture
= 1;
1153 inst
.Texture
.Texture
= j
;
1157 if (j
== TGSI_TEXTURE_COUNT
) {
1158 report_error( ctx
, "Expected texture target" );
1165 eat_opt_white( &cur
);
1166 for (i
= 0; inst
.Instruction
.Texture
&& *cur
== ',' && i
< TGSI_FULL_MAX_TEX_OFFSETS
; i
++) {
1168 eat_opt_white( &cur
);
1170 if (!parse_texoffset_operand( ctx
, &inst
.TexOffsets
[i
] ))
1173 eat_opt_white( &cur
);
1175 inst
.Texture
.NumOffsets
= i
;
1178 eat_opt_white(&cur
);
1180 for (; inst
.Instruction
.Memory
&& *cur
== ',';
1181 ctx
->cur
= cur
, eat_opt_white(&cur
)) {
1185 eat_opt_white(&cur
);
1187 j
= str_match_name_from_array(&cur
, tgsi_memory_names
,
1188 ARRAY_SIZE(tgsi_memory_names
));
1190 inst
.Memory
.Qualifier
|= 1U << j
;
1194 j
= str_match_name_from_array(&cur
, tgsi_texture_names
,
1195 ARRAY_SIZE(tgsi_texture_names
));
1197 inst
.Memory
.Texture
= j
;
1201 j
= str_match_format(&cur
);
1203 inst
.Memory
.Format
= j
;
1208 report_error(ctx
, "Expected memory qualifier, texture target, or format\n");
1213 eat_opt_white( &cur
);
1214 if (info
->is_branch
&& *cur
== ':') {
1218 eat_opt_white( &cur
);
1219 if (!parse_uint( &cur
, &target
)) {
1220 report_error( ctx
, "Expected a label" );
1223 inst
.Instruction
.Label
= 1;
1224 inst
.Label
.Label
= target
;
1228 advance
= tgsi_build_full_instruction(
1232 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1235 ctx
->tokens_cur
+= advance
;
1240 /* parses a 4-touple of the form {x, y, z, w}
1241 * where x, y, z, w are numbers */
1242 static boolean
parse_immediate_data(struct translate_ctx
*ctx
, unsigned type
,
1243 union tgsi_immediate_data
*values
)
1248 eat_opt_white( &ctx
->cur
);
1249 if (*ctx
->cur
!= '{') {
1250 report_error( ctx
, "Expected `{'" );
1254 for (i
= 0; i
< 4; i
++) {
1255 eat_opt_white( &ctx
->cur
);
1257 if (*ctx
->cur
!= ',') {
1258 report_error( ctx
, "Expected `,'" );
1262 eat_opt_white( &ctx
->cur
);
1266 case TGSI_IMM_FLOAT64
:
1267 ret
= parse_double(&ctx
->cur
, &values
[i
].Uint
, &values
[i
+1].Uint
);
1270 case TGSI_IMM_INT64
:
1271 ret
= parse_int64(&ctx
->cur
, &values
[i
].Uint
, &values
[i
+1].Uint
);
1274 case TGSI_IMM_UINT64
:
1275 ret
= parse_uint64(&ctx
->cur
, &values
[i
].Uint
, &values
[i
+1].Uint
);
1278 case TGSI_IMM_FLOAT32
:
1279 ret
= parse_float(&ctx
->cur
, &values
[i
].Float
);
1281 case TGSI_IMM_UINT32
:
1282 ret
= parse_uint(&ctx
->cur
, &values
[i
].Uint
);
1284 case TGSI_IMM_INT32
:
1285 ret
= parse_int(&ctx
->cur
, &values
[i
].Int
);
1294 report_error( ctx
, "Expected immediate constant" );
1298 eat_opt_white( &ctx
->cur
);
1299 if (*ctx
->cur
!= '}') {
1300 report_error( ctx
, "Expected `}'" );
1308 static boolean
parse_declaration( struct translate_ctx
*ctx
)
1310 struct tgsi_full_declaration decl
;
1312 struct parsed_dcl_bracket brackets
[2];
1315 const char *cur
, *cur2
;
1317 boolean is_vs_input
;
1319 if (!eat_white( &ctx
->cur
)) {
1320 report_error( ctx
, "Syntax error" );
1323 if (!parse_register_dcl( ctx
, &file
, brackets
, &num_brackets
))
1325 if (!parse_opt_writemask( ctx
, &writemask
))
1328 decl
= tgsi_default_full_declaration();
1329 decl
.Declaration
.File
= file
;
1330 decl
.Declaration
.UsageMask
= writemask
;
1332 if (num_brackets
== 1) {
1333 decl
.Range
.First
= brackets
[0].first
;
1334 decl
.Range
.Last
= brackets
[0].last
;
1336 decl
.Range
.First
= brackets
[1].first
;
1337 decl
.Range
.Last
= brackets
[1].last
;
1339 decl
.Declaration
.Dimension
= 1;
1340 decl
.Dim
.Index2D
= brackets
[0].first
;
1343 is_vs_input
= (file
== TGSI_FILE_INPUT
&&
1344 ctx
->processor
== PIPE_SHADER_VERTEX
);
1347 eat_opt_white( &cur
);
1351 eat_opt_white( &cur2
);
1352 if (str_match_nocase_whole( &cur2
, "ARRAY" )) {
1355 report_error( ctx
, "Expected `('" );
1359 eat_opt_white( &cur2
);
1360 if (!parse_int( &cur2
, &arrayid
)) {
1361 report_error( ctx
, "Expected `,'" );
1364 eat_opt_white( &cur2
);
1366 report_error( ctx
, "Expected `)'" );
1370 decl
.Declaration
.Array
= 1;
1371 decl
.Array
.ArrayID
= arrayid
;
1372 ctx
->cur
= cur
= cur2
;
1376 if (*cur
== ',' && !is_vs_input
) {
1380 eat_opt_white( &cur
);
1381 if (file
== TGSI_FILE_IMAGE
) {
1382 for (i
= 0; i
< TGSI_TEXTURE_COUNT
; i
++) {
1383 if (str_match_nocase_whole(&cur
, tgsi_texture_names
[i
])) {
1384 decl
.Image
.Resource
= i
;
1388 if (i
== TGSI_TEXTURE_COUNT
) {
1389 report_error(ctx
, "Expected texture target");
1394 eat_opt_white(&cur2
);
1395 while (*cur2
== ',') {
1397 eat_opt_white(&cur2
);
1398 if (str_match_nocase_whole(&cur2
, "RAW")) {
1401 } else if (str_match_nocase_whole(&cur2
, "WR")) {
1402 decl
.Image
.Writable
= 1;
1405 int format
= str_match_format(&cur2
);
1409 decl
.Image
.Format
= format
;
1412 eat_opt_white(&cur2
);
1417 } else if (file
== TGSI_FILE_SAMPLER_VIEW
) {
1418 for (i
= 0; i
< TGSI_TEXTURE_COUNT
; i
++) {
1419 if (str_match_nocase_whole(&cur
, tgsi_texture_names
[i
])) {
1420 decl
.SamplerView
.Resource
= i
;
1424 if (i
== TGSI_TEXTURE_COUNT
) {
1425 report_error(ctx
, "Expected texture target");
1428 eat_opt_white( &cur
);
1430 report_error( ctx
, "Expected `,'" );
1434 eat_opt_white( &cur
);
1435 for (j
= 0; j
< 4; ++j
) {
1436 for (i
= 0; i
< TGSI_RETURN_TYPE_COUNT
; ++i
) {
1437 if (str_match_nocase_whole(&cur
, tgsi_return_type_names
[i
])) {
1440 decl
.SamplerView
.ReturnTypeX
= i
;
1443 decl
.SamplerView
.ReturnTypeY
= i
;
1446 decl
.SamplerView
.ReturnTypeZ
= i
;
1449 decl
.SamplerView
.ReturnTypeW
= i
;
1457 if (i
== TGSI_RETURN_TYPE_COUNT
) {
1458 if (j
== 0 || j
> 2) {
1459 report_error(ctx
, "Expected type name");
1465 eat_opt_white( &cur2
);
1468 eat_opt_white( &cur2
);
1476 decl
.SamplerView
.ReturnTypeY
=
1477 decl
.SamplerView
.ReturnTypeZ
=
1478 decl
.SamplerView
.ReturnTypeW
=
1479 decl
.SamplerView
.ReturnTypeX
;
1482 } else if (file
== TGSI_FILE_BUFFER
) {
1483 if (str_match_nocase_whole(&cur
, "ATOMIC")) {
1484 decl
.Declaration
.Atomic
= 1;
1487 } else if (file
== TGSI_FILE_MEMORY
) {
1488 if (str_match_nocase_whole(&cur
, "GLOBAL")) {
1489 /* Note this is a no-op global is the default */
1490 decl
.Declaration
.MemType
= TGSI_MEMORY_TYPE_GLOBAL
;
1492 } else if (str_match_nocase_whole(&cur
, "SHARED")) {
1493 decl
.Declaration
.MemType
= TGSI_MEMORY_TYPE_SHARED
;
1495 } else if (str_match_nocase_whole(&cur
, "PRIVATE")) {
1496 decl
.Declaration
.MemType
= TGSI_MEMORY_TYPE_PRIVATE
;
1498 } else if (str_match_nocase_whole(&cur
, "INPUT")) {
1499 decl
.Declaration
.MemType
= TGSI_MEMORY_TYPE_INPUT
;
1503 if (str_match_nocase_whole(&cur
, "LOCAL")) {
1504 decl
.Declaration
.Local
= 1;
1509 eat_opt_white( &cur
);
1512 eat_opt_white( &cur
);
1514 for (i
= 0; i
< TGSI_SEMANTIC_COUNT
; i
++) {
1515 if (str_match_nocase_whole(&cur
, tgsi_semantic_names
[i
])) {
1519 eat_opt_white( &cur2
);
1522 eat_opt_white( &cur2
);
1523 if (!parse_uint( &cur2
, &index
)) {
1524 report_error( ctx
, "Expected literal integer" );
1527 eat_opt_white( &cur2
);
1529 report_error( ctx
, "Expected `]'" );
1534 decl
.Semantic
.Index
= index
;
1539 decl
.Declaration
.Semantic
= 1;
1540 decl
.Semantic
.Name
= i
;
1551 eat_opt_white( &cur
);
1553 file
== TGSI_FILE_OUTPUT
&& ctx
->processor
== PIPE_SHADER_GEOMETRY
) {
1555 eat_opt_white(&cur
);
1556 if (str_match_nocase_whole(&cur
, "STREAM")) {
1559 eat_opt_white(&cur
);
1561 report_error(ctx
, "Expected '('");
1566 for (int i
= 0; i
< 4; ++i
) {
1567 eat_opt_white(&cur
);
1568 if (!parse_uint(&cur
, &stream
[i
])) {
1569 report_error(ctx
, "Expected literal integer");
1573 eat_opt_white(&cur
);
1576 report_error(ctx
, "Expected ','");
1584 report_error(ctx
, "Expected ')'");
1589 decl
.Semantic
.StreamX
= stream
[0];
1590 decl
.Semantic
.StreamY
= stream
[1];
1591 decl
.Semantic
.StreamZ
= stream
[2];
1592 decl
.Semantic
.StreamW
= stream
[3];
1599 eat_opt_white( &cur
);
1600 if (*cur
== ',' && !is_vs_input
) {
1604 eat_opt_white( &cur
);
1605 for (i
= 0; i
< TGSI_INTERPOLATE_COUNT
; i
++) {
1606 if (str_match_nocase_whole( &cur
, tgsi_interpolate_names
[i
] )) {
1607 decl
.Declaration
.Interpolate
= 1;
1608 decl
.Interp
.Interpolate
= i
;
1614 if (i
== TGSI_INTERPOLATE_COUNT
) {
1615 report_error( ctx
, "Expected semantic or interpolate attribute" );
1621 eat_opt_white( &cur
);
1622 if (*cur
== ',' && !is_vs_input
) {
1626 eat_opt_white( &cur
);
1627 for (i
= 0; i
< TGSI_INTERPOLATE_LOC_COUNT
; i
++) {
1628 if (str_match_nocase_whole( &cur
, tgsi_interpolate_locations
[i
] )) {
1629 decl
.Interp
.Location
= i
;
1637 advance
= tgsi_build_full_declaration(
1641 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1645 ctx
->tokens_cur
+= advance
;
1650 static boolean
parse_immediate( struct translate_ctx
*ctx
)
1652 struct tgsi_full_immediate imm
;
1656 if (*ctx
->cur
== '[') {
1661 eat_opt_white( &ctx
->cur
);
1662 if (!parse_uint( &ctx
->cur
, &uindex
)) {
1663 report_error( ctx
, "Expected literal unsigned integer" );
1667 if (uindex
!= ctx
->num_immediates
) {
1668 report_error( ctx
, "Immediates must be sorted" );
1672 eat_opt_white( &ctx
->cur
);
1673 if (*ctx
->cur
!= ']') {
1674 report_error( ctx
, "Expected `]'" );
1681 if (!eat_white( &ctx
->cur
)) {
1682 report_error( ctx
, "Syntax error" );
1685 for (type
= 0; type
< ARRAY_SIZE(tgsi_immediate_type_names
); ++type
) {
1686 if (str_match_nocase_whole(&ctx
->cur
, tgsi_immediate_type_names
[type
]))
1689 if (type
== ARRAY_SIZE(tgsi_immediate_type_names
)) {
1690 report_error( ctx
, "Expected immediate type" );
1694 imm
= tgsi_default_full_immediate();
1695 imm
.Immediate
.NrTokens
+= 4;
1696 imm
.Immediate
.DataType
= type
;
1697 parse_immediate_data(ctx
, type
, imm
.u
);
1699 advance
= tgsi_build_full_immediate(
1703 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1706 ctx
->tokens_cur
+= advance
;
1708 ctx
->num_immediates
++;
1714 parse_primitive( const char **pcur
, uint
*primitive
)
1718 for (i
= 0; i
< PIPE_PRIM_MAX
; i
++) {
1719 const char *cur
= *pcur
;
1721 if (str_match_nocase_whole( &cur
, tgsi_primitive_names
[i
])) {
1731 parse_fs_coord_origin( const char **pcur
, uint
*fs_coord_origin
)
1735 for (i
= 0; i
< ARRAY_SIZE(tgsi_fs_coord_origin_names
); i
++) {
1736 const char *cur
= *pcur
;
1738 if (str_match_nocase_whole( &cur
, tgsi_fs_coord_origin_names
[i
])) {
1739 *fs_coord_origin
= i
;
1748 parse_fs_coord_pixel_center( const char **pcur
, uint
*fs_coord_pixel_center
)
1752 for (i
= 0; i
< ARRAY_SIZE(tgsi_fs_coord_pixel_center_names
); i
++) {
1753 const char *cur
= *pcur
;
1755 if (str_match_nocase_whole( &cur
, tgsi_fs_coord_pixel_center_names
[i
])) {
1756 *fs_coord_pixel_center
= i
;
1765 parse_property_next_shader( const char **pcur
, uint
*next_shader
)
1769 for (i
= 0; i
< ARRAY_SIZE(tgsi_processor_type_names
); i
++) {
1770 const char *cur
= *pcur
;
1772 if (str_match_nocase_whole( &cur
, tgsi_processor_type_names
[i
])) {
1781 static boolean
parse_property( struct translate_ctx
*ctx
)
1783 struct tgsi_full_property prop
;
1789 if (!eat_white( &ctx
->cur
)) {
1790 report_error( ctx
, "Syntax error" );
1793 if (!parse_identifier( &ctx
->cur
, id
, sizeof(id
) )) {
1794 report_error( ctx
, "Syntax error" );
1797 for (property_name
= 0; property_name
< TGSI_PROPERTY_COUNT
;
1799 if (streq_nocase_uprcase(tgsi_property_names
[property_name
], id
)) {
1803 if (property_name
>= TGSI_PROPERTY_COUNT
) {
1804 debug_printf( "\nError: Unknown property : '%s'", id
);
1808 eat_opt_white( &ctx
->cur
);
1809 switch(property_name
) {
1810 case TGSI_PROPERTY_GS_INPUT_PRIM
:
1811 case TGSI_PROPERTY_GS_OUTPUT_PRIM
:
1812 if (!parse_primitive(&ctx
->cur
, &values
[0] )) {
1813 report_error( ctx
, "Unknown primitive name as property!" );
1816 if (property_name
== TGSI_PROPERTY_GS_INPUT_PRIM
&&
1817 ctx
->processor
== PIPE_SHADER_GEOMETRY
) {
1818 ctx
->implied_array_size
= u_vertices_per_prim(values
[0]);
1821 case TGSI_PROPERTY_FS_COORD_ORIGIN
:
1822 if (!parse_fs_coord_origin(&ctx
->cur
, &values
[0] )) {
1823 report_error( ctx
, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1827 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER
:
1828 if (!parse_fs_coord_pixel_center(&ctx
->cur
, &values
[0] )) {
1829 report_error( ctx
, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1833 case TGSI_PROPERTY_NEXT_SHADER
:
1834 if (!parse_property_next_shader(&ctx
->cur
, &values
[0] )) {
1835 report_error( ctx
, "Unknown next shader property value." );
1839 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS
:
1841 if (!parse_uint(&ctx
->cur
, &values
[0] )) {
1842 report_error( ctx
, "Expected unsigned integer as property!" );
1847 prop
= tgsi_default_full_property();
1848 prop
.Property
.PropertyName
= property_name
;
1849 prop
.Property
.NrTokens
+= 1;
1850 prop
.u
[0].Data
= values
[0];
1852 advance
= tgsi_build_full_property(
1856 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1859 ctx
->tokens_cur
+= advance
;
1865 static boolean
translate( struct translate_ctx
*ctx
)
1867 eat_opt_white( &ctx
->cur
);
1868 if (!parse_header( ctx
))
1871 if (ctx
->processor
== PIPE_SHADER_TESS_CTRL
||
1872 ctx
->processor
== PIPE_SHADER_TESS_EVAL
)
1873 ctx
->implied_array_size
= 32;
1875 while (*ctx
->cur
!= '\0') {
1877 if (!eat_white( &ctx
->cur
)) {
1878 report_error( ctx
, "Syntax error" );
1882 if (*ctx
->cur
== '\0')
1884 if (parse_label( ctx
, &label_val
)) {
1885 if (!parse_instruction( ctx
, TRUE
))
1888 else if (str_match_nocase_whole( &ctx
->cur
, "DCL" )) {
1889 if (!parse_declaration( ctx
))
1892 else if (str_match_nocase_whole( &ctx
->cur
, "IMM" )) {
1893 if (!parse_immediate( ctx
))
1896 else if (str_match_nocase_whole( &ctx
->cur
, "PROPERTY" )) {
1897 if (!parse_property( ctx
))
1900 else if (!parse_instruction( ctx
, FALSE
)) {
1909 tgsi_text_translate(
1911 struct tgsi_token
*tokens
,
1914 struct translate_ctx ctx
= {0};
1918 ctx
.tokens
= tokens
;
1919 ctx
.tokens_cur
= tokens
;
1920 ctx
.tokens_end
= tokens
+ num_tokens
;
1922 if (!translate( &ctx
))
1925 return tgsi_sanity_check( tokens
);