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 static boolean
str_match_no_case( const char **pcur
, const char *str
)
86 const char *cur
= *pcur
;
88 while (*str
!= '\0' && *str
== uprcase( *cur
)) {
99 /* Eat zero or more whitespaces.
101 static void eat_opt_white( const char **pcur
)
103 while (**pcur
== ' ' || **pcur
== '\t' || **pcur
== '\n')
107 /* Eat one or more whitespaces.
108 * Return TRUE if at least one whitespace eaten.
110 static boolean
eat_white( const char **pcur
)
112 const char *cur
= *pcur
;
114 eat_opt_white( pcur
);
118 /* Parse unsigned integer.
119 * No checks for overflow.
121 static boolean
parse_uint( const char **pcur
, uint
*val
)
123 const char *cur
= *pcur
;
125 if (is_digit( cur
)) {
127 while (is_digit( cur
))
128 *val
= *val
* 10 + *cur
++ - '0';
135 static boolean
parse_identifier( const char **pcur
, char *ret
)
137 const char *cur
= *pcur
;
139 if (is_alpha_underscore( cur
)) {
141 while (is_alpha_underscore( cur
) || is_digit( cur
))
150 /* Parse floating point.
152 static boolean
parse_float( const char **pcur
, float *val
)
154 const char *cur
= *pcur
;
155 boolean integral_part
= FALSE
;
156 boolean fractional_part
= FALSE
;
158 *val
= (float) atof( cur
);
160 if (*cur
== '-' || *cur
== '+')
162 if (is_digit( cur
)) {
164 integral_part
= TRUE
;
165 while (is_digit( cur
))
170 if (is_digit( cur
)) {
172 fractional_part
= TRUE
;
173 while (is_digit( cur
))
177 if (!integral_part
&& !fractional_part
)
179 if (uprcase( *cur
) == 'E') {
181 if (*cur
== '-' || *cur
== '+')
183 if (is_digit( cur
)) {
185 while (is_digit( cur
))
199 struct tgsi_token
*tokens
;
200 struct tgsi_token
*tokens_cur
;
201 struct tgsi_token
*tokens_end
;
202 struct tgsi_header
*header
;
203 unsigned processor
: 4;
204 int implied_array_size
: 5;
207 static void report_error( struct translate_ctx
*ctx
, const char *msg
)
211 const char *itr
= ctx
->text
;
213 while (itr
!= ctx
->cur
) {
222 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg
, line
, column
);
225 /* Parse shader header.
226 * Return TRUE for one of the following headers.
231 static boolean
parse_header( struct translate_ctx
*ctx
)
235 if (str_match_no_case( &ctx
->cur
, "FRAG" ))
236 processor
= TGSI_PROCESSOR_FRAGMENT
;
237 else if (str_match_no_case( &ctx
->cur
, "VERT" ))
238 processor
= TGSI_PROCESSOR_VERTEX
;
239 else if (str_match_no_case( &ctx
->cur
, "GEOM" ))
240 processor
= TGSI_PROCESSOR_GEOMETRY
;
241 else if (str_match_no_case( &ctx
->cur
, "COMP" ))
242 processor
= TGSI_PROCESSOR_COMPUTE
;
244 report_error( ctx
, "Unknown header" );
248 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
250 ctx
->header
= (struct tgsi_header
*) ctx
->tokens_cur
++;
251 *ctx
->header
= tgsi_build_header();
253 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
255 *(struct tgsi_processor
*) ctx
->tokens_cur
++ = tgsi_build_processor( processor
, ctx
->header
);
256 ctx
->processor
= processor
;
261 static boolean
parse_label( struct translate_ctx
*ctx
, uint
*val
)
263 const char *cur
= ctx
->cur
;
265 if (parse_uint( &cur
, val
)) {
266 eat_opt_white( &cur
);
277 parse_file( const char **pcur
, uint
*file
)
281 for (i
= 0; i
< TGSI_FILE_COUNT
; i
++) {
282 const char *cur
= *pcur
;
284 if (str_match_no_case( &cur
, tgsi_file_names
[i
] )) {
285 if (!is_digit_alpha_underscore( cur
)) {
297 struct translate_ctx
*ctx
,
303 eat_opt_white( &cur
);
306 *writemask
= TGSI_WRITEMASK_NONE
;
307 eat_opt_white( &cur
);
308 if (uprcase( *cur
) == 'X') {
310 *writemask
|= TGSI_WRITEMASK_X
;
312 if (uprcase( *cur
) == 'Y') {
314 *writemask
|= TGSI_WRITEMASK_Y
;
316 if (uprcase( *cur
) == 'Z') {
318 *writemask
|= TGSI_WRITEMASK_Z
;
320 if (uprcase( *cur
) == 'W') {
322 *writemask
|= TGSI_WRITEMASK_W
;
325 if (*writemask
== TGSI_WRITEMASK_NONE
) {
326 report_error( ctx
, "Writemask expected" );
333 *writemask
= TGSI_WRITEMASK_XYZW
;
339 /* <register_file_bracket> ::= <file> `['
342 parse_register_file_bracket(
343 struct translate_ctx
*ctx
,
346 if (!parse_file( &ctx
->cur
, file
)) {
347 report_error( ctx
, "Unknown register file" );
350 eat_opt_white( &ctx
->cur
);
351 if (*ctx
->cur
!= '[') {
352 report_error( ctx
, "Expected `['" );
359 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
362 parse_register_file_bracket_index(
363 struct translate_ctx
*ctx
,
369 if (!parse_register_file_bracket( ctx
, file
))
371 eat_opt_white( &ctx
->cur
);
372 if (!parse_uint( &ctx
->cur
, &uindex
)) {
373 report_error( ctx
, "Expected literal unsigned integer" );
376 *index
= (int) uindex
;
380 /* Parse simple 1d register operand.
381 * <register_dst> ::= <register_file_bracket_index> `]'
384 parse_register_1d(struct translate_ctx
*ctx
,
388 if (!parse_register_file_bracket_index( ctx
, file
, index
))
390 eat_opt_white( &ctx
->cur
);
391 if (*ctx
->cur
!= ']') {
392 report_error( ctx
, "Expected `]'" );
399 struct parsed_bracket
{
409 parse_register_bracket(
410 struct translate_ctx
*ctx
,
411 struct parsed_bracket
*brackets
)
416 memset(brackets
, 0, sizeof(struct parsed_bracket
));
418 eat_opt_white( &ctx
->cur
);
421 if (parse_file( &cur
, &brackets
->ind_file
)) {
422 if (!parse_register_1d( ctx
, &brackets
->ind_file
,
423 &brackets
->ind_index
))
425 eat_opt_white( &ctx
->cur
);
427 if (*ctx
->cur
== '.') {
429 eat_opt_white(&ctx
->cur
);
431 switch (uprcase(*ctx
->cur
)) {
433 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
436 brackets
->ind_comp
= TGSI_SWIZZLE_Y
;
439 brackets
->ind_comp
= TGSI_SWIZZLE_Z
;
442 brackets
->ind_comp
= TGSI_SWIZZLE_W
;
445 report_error(ctx
, "Expected indirect register swizzle component `x', `y', `z' or `w'");
449 eat_opt_white(&ctx
->cur
);
452 if (*ctx
->cur
== '+' || *ctx
->cur
== '-') {
455 negate
= *ctx
->cur
== '-';
457 eat_opt_white( &ctx
->cur
);
458 if (!parse_uint( &ctx
->cur
, &uindex
)) {
459 report_error( ctx
, "Expected literal unsigned integer" );
463 brackets
->index
= -(int) uindex
;
465 brackets
->index
= (int) uindex
;
472 if (!parse_uint( &ctx
->cur
, &uindex
)) {
473 report_error( ctx
, "Expected literal unsigned integer" );
476 brackets
->index
= (int) uindex
;
477 brackets
->ind_file
= TGSI_FILE_NULL
;
478 brackets
->ind_index
= 0;
480 eat_opt_white( &ctx
->cur
);
481 if (*ctx
->cur
!= ']') {
482 report_error( ctx
, "Expected `]'" );
490 parse_opt_register_src_bracket(
491 struct translate_ctx
*ctx
,
492 struct parsed_bracket
*brackets
,
493 int *parsed_brackets
)
495 const char *cur
= ctx
->cur
;
497 *parsed_brackets
= 0;
499 eat_opt_white( &cur
);
504 if (!parse_register_bracket(ctx
, brackets
))
507 *parsed_brackets
= 1;
514 /* Parse source register operand.
515 * <register_src> ::= <register_file_bracket_index> `]' |
516 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
517 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
518 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
522 struct translate_ctx
*ctx
,
524 struct parsed_bracket
*brackets
)
526 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
527 if (!parse_register_file_bracket( ctx
, file
))
529 if (!parse_register_bracket( ctx
, brackets
))
535 struct parsed_dcl_bracket
{
541 parse_register_dcl_bracket(
542 struct translate_ctx
*ctx
,
543 struct parsed_dcl_bracket
*bracket
)
546 memset(bracket
, 0, sizeof(struct parsed_dcl_bracket
));
548 eat_opt_white( &ctx
->cur
);
550 if (!parse_uint( &ctx
->cur
, &uindex
)) {
551 /* it can be an empty bracket [] which means its range
552 * is from 0 to some implied size */
553 if (ctx
->cur
[0] == ']' && ctx
->implied_array_size
!= 0) {
555 bracket
->last
= ctx
->implied_array_size
- 1;
558 report_error( ctx
, "Expected literal unsigned integer" );
561 bracket
->first
= uindex
;
563 eat_opt_white( &ctx
->cur
);
565 if (ctx
->cur
[0] == '.' && ctx
->cur
[1] == '.') {
569 eat_opt_white( &ctx
->cur
);
570 if (!parse_uint( &ctx
->cur
, &uindex
)) {
571 report_error( ctx
, "Expected literal integer" );
574 bracket
->last
= (int) uindex
;
575 eat_opt_white( &ctx
->cur
);
578 bracket
->last
= bracket
->first
;
582 if (*ctx
->cur
!= ']') {
583 report_error( ctx
, "Expected `]' or `..'" );
590 /* Parse register declaration.
591 * <register_dcl> ::= <register_file_bracket_index> `]' |
592 * <register_file_bracket_index> `..' <index> `]'
596 struct translate_ctx
*ctx
,
598 struct parsed_dcl_bracket
*brackets
,
605 if (!parse_register_file_bracket( ctx
, file
))
607 if (!parse_register_dcl_bracket( ctx
, &brackets
[0] ))
613 eat_opt_white( &cur
);
618 if (!parse_register_dcl_bracket( ctx
, &brackets
[1] ))
620 /* for geometry shader we don't really care about
621 * the first brackets it's always the size of the
622 * input primitive. so we want to declare just
623 * the index relevant to the semantics which is in
624 * the second bracket */
625 if (ctx
->processor
== TGSI_PROCESSOR_GEOMETRY
&& *file
== TGSI_FILE_INPUT
) {
626 brackets
[0] = brackets
[1];
637 /* Parse destination register operand.*/
640 struct translate_ctx
*ctx
,
642 struct parsed_bracket
*brackets
)
644 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
645 if (!parse_register_file_bracket( ctx
, file
))
647 if (!parse_register_bracket( ctx
, brackets
))
655 struct translate_ctx
*ctx
,
656 struct tgsi_full_dst_register
*dst
)
661 struct parsed_bracket bracket
[2];
662 int parsed_opt_brackets
;
664 if (!parse_register_dst( ctx
, &file
, &bracket
[0] ))
666 if (!parse_opt_register_src_bracket(ctx
, &bracket
[1], &parsed_opt_brackets
))
670 eat_opt_white( &cur
);
672 if (!parse_opt_writemask( ctx
, &writemask
))
675 dst
->Register
.File
= file
;
676 if (parsed_opt_brackets
) {
677 dst
->Register
.Dimension
= 1;
678 dst
->Dimension
.Indirect
= 0;
679 dst
->Dimension
.Dimension
= 0;
680 dst
->Dimension
.Index
= bracket
[0].index
;
681 bracket
[0] = bracket
[1];
683 dst
->Register
.Index
= bracket
[0].index
;
684 dst
->Register
.WriteMask
= writemask
;
685 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
686 dst
->Register
.Indirect
= 1;
687 dst
->Indirect
.File
= bracket
[0].ind_file
;
688 dst
->Indirect
.Index
= bracket
[0].ind_index
;
689 dst
->Indirect
.SwizzleX
= bracket
[0].ind_comp
;
690 dst
->Indirect
.SwizzleY
= bracket
[0].ind_comp
;
691 dst
->Indirect
.SwizzleZ
= bracket
[0].ind_comp
;
692 dst
->Indirect
.SwizzleW
= bracket
[0].ind_comp
;
698 parse_optional_swizzle(
699 struct translate_ctx
*ctx
,
701 boolean
*parsed_swizzle
)
703 const char *cur
= ctx
->cur
;
705 *parsed_swizzle
= FALSE
;
707 eat_opt_white( &cur
);
712 eat_opt_white( &cur
);
713 for (i
= 0; i
< 4; i
++) {
714 if (uprcase( *cur
) == 'X')
715 swizzle
[i
] = TGSI_SWIZZLE_X
;
716 else if (uprcase( *cur
) == 'Y')
717 swizzle
[i
] = TGSI_SWIZZLE_Y
;
718 else if (uprcase( *cur
) == 'Z')
719 swizzle
[i
] = TGSI_SWIZZLE_Z
;
720 else if (uprcase( *cur
) == 'W')
721 swizzle
[i
] = TGSI_SWIZZLE_W
;
723 report_error( ctx
, "Expected register swizzle component `x', `y', `z' or `w'" );
728 *parsed_swizzle
= TRUE
;
736 struct translate_ctx
*ctx
,
737 struct tgsi_full_src_register
*src
)
741 boolean parsed_swizzle
;
742 struct parsed_bracket bracket
[2];
743 int parsed_opt_brackets
;
745 if (*ctx
->cur
== '-') {
747 eat_opt_white( &ctx
->cur
);
748 src
->Register
.Negate
= 1;
751 if (*ctx
->cur
== '|') {
753 eat_opt_white( &ctx
->cur
);
754 src
->Register
.Absolute
= 1;
757 if (!parse_register_src(ctx
, &file
, &bracket
[0]))
759 if (!parse_opt_register_src_bracket(ctx
, &bracket
[1], &parsed_opt_brackets
))
762 src
->Register
.File
= file
;
763 if (parsed_opt_brackets
) {
764 src
->Register
.Dimension
= 1;
765 src
->Dimension
.Indirect
= 0;
766 src
->Dimension
.Dimension
= 0;
767 src
->Dimension
.Index
= bracket
[0].index
;
768 bracket
[0] = bracket
[1];
770 src
->Register
.Index
= bracket
[0].index
;
771 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
772 src
->Register
.Indirect
= 1;
773 src
->Indirect
.File
= bracket
[0].ind_file
;
774 src
->Indirect
.Index
= bracket
[0].ind_index
;
775 src
->Indirect
.SwizzleX
= bracket
[0].ind_comp
;
776 src
->Indirect
.SwizzleY
= bracket
[0].ind_comp
;
777 src
->Indirect
.SwizzleZ
= bracket
[0].ind_comp
;
778 src
->Indirect
.SwizzleW
= bracket
[0].ind_comp
;
781 /* Parse optional swizzle.
783 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
)) {
784 if (parsed_swizzle
) {
785 src
->Register
.SwizzleX
= swizzle
[0];
786 src
->Register
.SwizzleY
= swizzle
[1];
787 src
->Register
.SwizzleZ
= swizzle
[2];
788 src
->Register
.SwizzleW
= swizzle
[3];
792 if (src
->Register
.Absolute
) {
793 eat_opt_white( &ctx
->cur
);
794 if (*ctx
->cur
!= '|') {
795 report_error( ctx
, "Expected `|'" );
806 match_inst_mnemonic(const char **pcur
,
807 const struct tgsi_opcode_info
*info
)
809 if (str_match_no_case(pcur
, info
->mnemonic
)) {
817 struct translate_ctx
*ctx
,
821 uint saturate
= TGSI_SAT_NONE
;
822 const struct tgsi_opcode_info
*info
;
823 struct tgsi_full_instruction inst
;
827 inst
= tgsi_default_full_instruction();
831 eat_opt_white( &ctx
->cur
);
832 if (*ctx
->cur
== '(') {
836 boolean parsed_swizzle
;
838 inst
.Instruction
.Predicate
= 1;
841 if (*ctx
->cur
== '!') {
843 inst
.Predicate
.Negate
= 1;
846 if (!parse_register_1d( ctx
, &file
, &index
))
849 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
)) {
850 if (parsed_swizzle
) {
851 inst
.Predicate
.SwizzleX
= swizzle
[0];
852 inst
.Predicate
.SwizzleY
= swizzle
[1];
853 inst
.Predicate
.SwizzleZ
= swizzle
[2];
854 inst
.Predicate
.SwizzleW
= swizzle
[3];
858 if (*ctx
->cur
!= ')') {
859 report_error( ctx
, "Expected `)'" );
866 /* Parse instruction name.
868 eat_opt_white( &ctx
->cur
);
869 for (i
= 0; i
< TGSI_OPCODE_LAST
; i
++) {
872 info
= tgsi_get_opcode_info( i
);
873 if (match_inst_mnemonic(&cur
, info
)) {
874 if (str_match_no_case( &cur
, "_SATNV" ))
875 saturate
= TGSI_SAT_MINUS_PLUS_ONE
;
876 else if (str_match_no_case( &cur
, "_SAT" ))
877 saturate
= TGSI_SAT_ZERO_ONE
;
879 if (info
->num_dst
+ info
->num_src
+ info
->is_tex
== 0) {
880 if (!is_digit_alpha_underscore( cur
)) {
885 else if (*cur
== '\0' || eat_white( &cur
)) {
891 if (i
== TGSI_OPCODE_LAST
) {
893 report_error( ctx
, "Unknown opcode" );
895 report_error( ctx
, "Expected `DCL', `IMM' or a label" );
899 inst
.Instruction
.Opcode
= i
;
900 inst
.Instruction
.Saturate
= saturate
;
901 inst
.Instruction
.NumDstRegs
= info
->num_dst
;
902 inst
.Instruction
.NumSrcRegs
= info
->num_src
;
904 /* Parse instruction operands.
906 for (i
= 0; i
< info
->num_dst
+ info
->num_src
+ info
->is_tex
; i
++) {
908 eat_opt_white( &ctx
->cur
);
909 if (*ctx
->cur
!= ',') {
910 report_error( ctx
, "Expected `,'" );
914 eat_opt_white( &ctx
->cur
);
917 if (i
< info
->num_dst
) {
918 if (!parse_dst_operand( ctx
, &inst
.Dst
[i
] ))
921 else if (i
< info
->num_dst
+ info
->num_src
) {
922 if (!parse_src_operand( ctx
, &inst
.Src
[i
- info
->num_dst
] ))
928 for (j
= 0; j
< TGSI_TEXTURE_COUNT
; j
++) {
929 if (str_match_no_case( &ctx
->cur
, tgsi_texture_names
[j
] )) {
930 if (!is_digit_alpha_underscore( ctx
->cur
)) {
931 inst
.Instruction
.Texture
= 1;
932 inst
.Texture
.Texture
= j
;
937 if (j
== TGSI_TEXTURE_COUNT
) {
938 report_error( ctx
, "Expected texture target" );
945 eat_opt_white( &cur
);
946 if (info
->is_branch
&& *cur
== ':') {
950 eat_opt_white( &cur
);
951 if (!parse_uint( &cur
, &target
)) {
952 report_error( ctx
, "Expected a label" );
955 inst
.Instruction
.Label
= 1;
956 inst
.Label
.Label
= target
;
960 advance
= tgsi_build_full_instruction(
964 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
967 ctx
->tokens_cur
+= advance
;
972 /* parses a 4-touple of the form {x, y, z, w}
973 * where x, y, z, w are numbers */
974 static boolean
parse_immediate_data(struct translate_ctx
*ctx
,
979 eat_opt_white( &ctx
->cur
);
980 if (*ctx
->cur
!= '{') {
981 report_error( ctx
, "Expected `{'" );
985 for (i
= 0; i
< 4; i
++) {
986 eat_opt_white( &ctx
->cur
);
988 if (*ctx
->cur
!= ',') {
989 report_error( ctx
, "Expected `,'" );
993 eat_opt_white( &ctx
->cur
);
995 if (!parse_float( &ctx
->cur
, &values
[i
] )) {
996 report_error( ctx
, "Expected literal floating point" );
1000 eat_opt_white( &ctx
->cur
);
1001 if (*ctx
->cur
!= '}') {
1002 report_error( ctx
, "Expected `}'" );
1010 static boolean
parse_declaration( struct translate_ctx
*ctx
)
1012 struct tgsi_full_declaration decl
;
1014 struct parsed_dcl_bracket brackets
[2];
1017 const char *cur
, *cur2
;
1019 boolean is_vs_input
;
1020 boolean is_imm_array
;
1022 if (!eat_white( &ctx
->cur
)) {
1023 report_error( ctx
, "Syntax error" );
1026 if (!parse_register_dcl( ctx
, &file
, brackets
, &num_brackets
))
1028 if (!parse_opt_writemask( ctx
, &writemask
))
1031 decl
= tgsi_default_full_declaration();
1032 decl
.Declaration
.File
= file
;
1033 decl
.Declaration
.UsageMask
= writemask
;
1035 if (num_brackets
== 1) {
1036 decl
.Range
.First
= brackets
[0].first
;
1037 decl
.Range
.Last
= brackets
[0].last
;
1039 decl
.Range
.First
= brackets
[1].first
;
1040 decl
.Range
.Last
= brackets
[1].last
;
1042 decl
.Declaration
.Dimension
= 1;
1043 decl
.Dim
.Index2D
= brackets
[0].first
;
1046 is_vs_input
= (file
== TGSI_FILE_INPUT
&&
1047 ctx
->processor
== TGSI_PROCESSOR_VERTEX
);
1048 is_imm_array
= (file
== TGSI_FILE_IMMEDIATE_ARRAY
);
1051 eat_opt_white( &cur
);
1052 if (*cur
== ',' && !is_vs_input
) {
1056 eat_opt_white( &cur
);
1057 if (file
== TGSI_FILE_RESOURCE
) {
1058 for (i
= 0; i
< TGSI_TEXTURE_COUNT
; i
++) {
1059 if (str_match_no_case(&cur
, tgsi_texture_names
[i
])) {
1060 if (!is_digit_alpha_underscore(cur
)) {
1061 decl
.Resource
.Resource
= i
;
1066 if (i
== TGSI_TEXTURE_COUNT
) {
1067 report_error(ctx
, "Expected texture target");
1072 eat_opt_white(&cur2
);
1073 while (*cur2
== ',') {
1075 eat_opt_white(&cur2
);
1076 if (str_match_no_case(&cur2
, "RAW") &&
1077 !is_digit_alpha_underscore(cur2
)) {
1078 decl
.Resource
.Raw
= 1;
1080 } else if (str_match_no_case(&cur2
, "WR") &&
1081 !is_digit_alpha_underscore(cur2
)) {
1082 decl
.Resource
.Writable
= 1;
1088 eat_opt_white(&cur2
);
1093 } else if (file
== TGSI_FILE_SAMPLER_VIEW
) {
1094 for (i
= 0; i
< TGSI_TEXTURE_COUNT
; i
++) {
1095 if (str_match_no_case(&cur
, tgsi_texture_names
[i
])) {
1096 if (!is_digit_alpha_underscore(cur
)) {
1097 decl
.SamplerView
.Resource
= i
;
1102 if (i
== TGSI_TEXTURE_COUNT
) {
1103 report_error(ctx
, "Expected texture target");
1106 eat_opt_white( &cur
);
1108 report_error( ctx
, "Expected `,'" );
1112 eat_opt_white( &cur
);
1113 for (j
= 0; j
< 4; ++j
) {
1114 for (i
= 0; i
< PIPE_TYPE_COUNT
; ++i
) {
1115 if (str_match_no_case(&cur
, tgsi_type_names
[i
])) {
1116 if (!is_digit_alpha_underscore(cur
)) {
1119 decl
.SamplerView
.ReturnTypeX
= i
;
1122 decl
.SamplerView
.ReturnTypeY
= i
;
1125 decl
.SamplerView
.ReturnTypeZ
= i
;
1128 decl
.SamplerView
.ReturnTypeW
= i
;
1137 if (i
== PIPE_TYPE_COUNT
) {
1138 if (j
== 0 || j
> 2) {
1139 report_error(ctx
, "Expected type name");
1145 eat_opt_white( &cur2
);
1148 eat_opt_white( &cur2
);
1156 decl
.SamplerView
.ReturnTypeY
=
1157 decl
.SamplerView
.ReturnTypeZ
=
1158 decl
.SamplerView
.ReturnTypeW
=
1159 decl
.SamplerView
.ReturnTypeX
;
1163 if (str_match_no_case(&cur
, "LOCAL") &&
1164 !is_digit_alpha_underscore(cur
)) {
1165 decl
.Declaration
.Local
= 1;
1170 eat_opt_white( &cur
);
1173 eat_opt_white( &cur
);
1175 for (i
= 0; i
< TGSI_SEMANTIC_COUNT
; i
++) {
1176 if (str_match_no_case( &cur
, tgsi_semantic_names
[i
] )) {
1179 if (is_digit_alpha_underscore( cur
))
1182 eat_opt_white( &cur2
);
1185 eat_opt_white( &cur2
);
1186 if (!parse_uint( &cur2
, &index
)) {
1187 report_error( ctx
, "Expected literal integer" );
1190 eat_opt_white( &cur2
);
1192 report_error( ctx
, "Expected `]'" );
1197 decl
.Semantic
.Index
= index
;
1202 decl
.Declaration
.Semantic
= 1;
1203 decl
.Semantic
.Name
= i
;
1211 } else if (is_imm_array
) {
1214 /* we have our immediate data */
1216 report_error( ctx
, "Immediate array without data" );
1222 decl
.ImmediateData
.u
=
1223 MALLOC(sizeof(union tgsi_immediate_data
) * 4 *
1224 (decl
.Range
.Last
+ 1));
1225 vals_itr
= (float*)decl
.ImmediateData
.u
;
1226 for (i
= 0; i
<= decl
.Range
.Last
; ++i
) {
1227 if (!parse_immediate_data(ctx
, vals_itr
)) {
1228 FREE(decl
.ImmediateData
.u
);
1232 eat_opt_white( &ctx
->cur
);
1233 if (*ctx
->cur
!= ',') {
1234 if (i
!= decl
.Range
.Last
) {
1235 report_error( ctx
, "Not enough data in immediate array!" );
1236 FREE(decl
.ImmediateData
.u
);
1242 eat_opt_white( &ctx
->cur
);
1243 if (*ctx
->cur
!= '}') {
1244 FREE(decl
.ImmediateData
.u
);
1245 report_error( ctx
, "Immediate array data missing closing '}'" );
1252 eat_opt_white( &cur
);
1253 if (*cur
== ',' && !is_vs_input
) {
1257 eat_opt_white( &cur
);
1258 for (i
= 0; i
< TGSI_INTERPOLATE_COUNT
; i
++) {
1259 if (str_match_no_case( &cur
, tgsi_interpolate_names
[i
] )) {
1260 if (is_digit_alpha_underscore( cur
))
1262 decl
.Declaration
.Interpolate
= 1;
1263 decl
.Interp
.Interpolate
= i
;
1269 if (i
== TGSI_INTERPOLATE_COUNT
) {
1270 report_error( ctx
, "Expected semantic or interpolate attribute" );
1275 advance
= tgsi_build_full_declaration(
1279 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1282 FREE(decl
.ImmediateData
.u
);
1286 ctx
->tokens_cur
+= advance
;
1291 static boolean
parse_immediate( struct translate_ctx
*ctx
)
1293 struct tgsi_full_immediate imm
;
1297 if (!eat_white( &ctx
->cur
)) {
1298 report_error( ctx
, "Syntax error" );
1301 if (!str_match_no_case( &ctx
->cur
, "FLT32" ) ||
1302 is_digit_alpha_underscore( ctx
->cur
)) {
1303 report_error( ctx
, "Expected `FLT32'" );
1307 parse_immediate_data(ctx
, values
);
1309 imm
= tgsi_default_full_immediate();
1310 imm
.Immediate
.NrTokens
+= 4;
1311 imm
.Immediate
.DataType
= TGSI_IMM_FLOAT32
;
1312 imm
.u
[0].Float
= values
[0];
1313 imm
.u
[1].Float
= values
[1];
1314 imm
.u
[2].Float
= values
[2];
1315 imm
.u
[3].Float
= values
[3];
1317 advance
= tgsi_build_full_immediate(
1321 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1324 ctx
->tokens_cur
+= advance
;
1330 parse_primitive( const char **pcur
, uint
*primitive
)
1334 for (i
= 0; i
< PIPE_PRIM_MAX
; i
++) {
1335 const char *cur
= *pcur
;
1337 if (str_match_no_case( &cur
, tgsi_primitive_names
[i
])) {
1347 parse_fs_coord_origin( const char **pcur
, uint
*fs_coord_origin
)
1351 for (i
= 0; i
< Elements(tgsi_fs_coord_origin_names
); i
++) {
1352 const char *cur
= *pcur
;
1354 if (str_match_no_case( &cur
, tgsi_fs_coord_origin_names
[i
])) {
1355 *fs_coord_origin
= i
;
1364 parse_fs_coord_pixel_center( const char **pcur
, uint
*fs_coord_pixel_center
)
1368 for (i
= 0; i
< Elements(tgsi_fs_coord_pixel_center_names
); i
++) {
1369 const char *cur
= *pcur
;
1371 if (str_match_no_case( &cur
, tgsi_fs_coord_pixel_center_names
[i
])) {
1372 *fs_coord_pixel_center
= i
;
1381 static boolean
parse_property( struct translate_ctx
*ctx
)
1383 struct tgsi_full_property prop
;
1389 if (!eat_white( &ctx
->cur
)) {
1390 report_error( ctx
, "Syntax error" );
1393 if (!parse_identifier( &ctx
->cur
, id
)) {
1394 report_error( ctx
, "Syntax error" );
1397 for (property_name
= 0; property_name
< TGSI_PROPERTY_COUNT
;
1399 if (streq_nocase_uprcase(tgsi_property_names
[property_name
], id
)) {
1403 if (property_name
>= TGSI_PROPERTY_COUNT
) {
1404 debug_printf( "\nError: Unknown property : '%s'", id
);
1408 eat_opt_white( &ctx
->cur
);
1409 switch(property_name
) {
1410 case TGSI_PROPERTY_GS_INPUT_PRIM
:
1411 case TGSI_PROPERTY_GS_OUTPUT_PRIM
:
1412 if (!parse_primitive(&ctx
->cur
, &values
[0] )) {
1413 report_error( ctx
, "Unknown primitive name as property!" );
1416 if (property_name
== TGSI_PROPERTY_GS_INPUT_PRIM
&&
1417 ctx
->processor
== TGSI_PROCESSOR_GEOMETRY
) {
1418 ctx
->implied_array_size
= u_vertices_per_prim(values
[0]);
1421 case TGSI_PROPERTY_FS_COORD_ORIGIN
:
1422 if (!parse_fs_coord_origin(&ctx
->cur
, &values
[0] )) {
1423 report_error( ctx
, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1427 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER
:
1428 if (!parse_fs_coord_pixel_center(&ctx
->cur
, &values
[0] )) {
1429 report_error( ctx
, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1433 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS
:
1435 if (!parse_uint(&ctx
->cur
, &values
[0] )) {
1436 report_error( ctx
, "Expected unsigned integer as property!" );
1441 prop
= tgsi_default_full_property();
1442 prop
.Property
.PropertyName
= property_name
;
1443 prop
.Property
.NrTokens
+= 1;
1444 prop
.u
[0].Data
= values
[0];
1446 advance
= tgsi_build_full_property(
1450 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1453 ctx
->tokens_cur
+= advance
;
1459 static boolean
translate( struct translate_ctx
*ctx
)
1461 eat_opt_white( &ctx
->cur
);
1462 if (!parse_header( ctx
))
1465 while (*ctx
->cur
!= '\0') {
1467 if (!eat_white( &ctx
->cur
)) {
1468 report_error( ctx
, "Syntax error" );
1472 if (*ctx
->cur
== '\0')
1474 if (parse_label( ctx
, &label_val
)) {
1475 if (!parse_instruction( ctx
, TRUE
))
1478 else if (str_match_no_case( &ctx
->cur
, "DCL" )) {
1479 if (!parse_declaration( ctx
))
1482 else if (str_match_no_case( &ctx
->cur
, "IMM" )) {
1483 if (!parse_immediate( ctx
))
1486 else if (str_match_no_case( &ctx
->cur
, "PROPERTY" )) {
1487 if (!parse_property( ctx
))
1490 else if (!parse_instruction( ctx
, FALSE
)) {
1499 tgsi_text_translate(
1501 struct tgsi_token
*tokens
,
1504 struct translate_ctx ctx
;
1508 ctx
.tokens
= tokens
;
1509 ctx
.tokens_cur
= tokens
;
1510 ctx
.tokens_end
= tokens
+ num_tokens
;
1512 if (!translate( &ctx
))
1515 return tgsi_sanity_check( tokens
);