1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include "util/u_debug.h"
29 #include "util/u_memory.h"
30 #include "util/u_prim.h"
31 #include "pipe/p_defines.h"
32 #include "util/u_inlines.h"
33 #include "tgsi_text.h"
34 #include "tgsi_build.h"
35 #include "tgsi_info.h"
36 #include "tgsi_parse.h"
37 #include "tgsi_sanity.h"
38 #include "tgsi_util.h"
39 #include "tgsi_dump.h"
41 static boolean
is_alpha_underscore( const char *cur
)
44 (*cur
>= 'a' && *cur
<= 'z') ||
45 (*cur
>= 'A' && *cur
<= 'Z') ||
49 static boolean
is_digit( const char *cur
)
51 return *cur
>= '0' && *cur
<= '9';
54 static boolean
is_digit_alpha_underscore( const char *cur
)
56 return is_digit( cur
) || is_alpha_underscore( cur
);
59 static char uprcase( char c
)
61 if (c
>= 'a' && c
<= 'z')
67 * Ignore case of str1 and assume str1 is already uppercase.
68 * Return TRUE iff str1 and str2 are equal.
71 streq_nocase_uprcase(const char *str1
,
74 while (*str1
&& *str2
) {
75 if (*str1
!= uprcase(*str2
))
80 return *str1
== 0 && *str2
== 0;
83 static boolean
str_match_no_case( const char **pcur
, const char *str
)
85 const char *cur
= *pcur
;
87 while (*str
!= '\0' && *str
== uprcase( *cur
)) {
98 /* Eat zero or more whitespaces.
100 static void eat_opt_white( const char **pcur
)
102 while (**pcur
== ' ' || **pcur
== '\t' || **pcur
== '\n')
106 /* Eat one or more whitespaces.
107 * Return TRUE if at least one whitespace eaten.
109 static boolean
eat_white( const char **pcur
)
111 const char *cur
= *pcur
;
113 eat_opt_white( pcur
);
117 /* Parse unsigned integer.
118 * No checks for overflow.
120 static boolean
parse_uint( const char **pcur
, uint
*val
)
122 const char *cur
= *pcur
;
124 if (is_digit( cur
)) {
126 while (is_digit( cur
))
127 *val
= *val
* 10 + *cur
++ - '0';
134 static boolean
parse_identifier( const char **pcur
, char *ret
)
136 const char *cur
= *pcur
;
138 if (is_alpha_underscore( cur
)) {
140 while (is_alpha_underscore( cur
) || is_digit( cur
))
149 /* Parse floating point.
151 static boolean
parse_float( const char **pcur
, float *val
)
153 const char *cur
= *pcur
;
154 boolean integral_part
= FALSE
;
155 boolean fractional_part
= FALSE
;
157 *val
= (float) atof( cur
);
159 if (*cur
== '-' || *cur
== '+')
161 if (is_digit( cur
)) {
163 integral_part
= TRUE
;
164 while (is_digit( cur
))
169 if (is_digit( cur
)) {
171 fractional_part
= TRUE
;
172 while (is_digit( cur
))
176 if (!integral_part
&& !fractional_part
)
178 if (uprcase( *cur
) == 'E') {
180 if (*cur
== '-' || *cur
== '+')
182 if (is_digit( cur
)) {
184 while (is_digit( cur
))
198 struct tgsi_token
*tokens
;
199 struct tgsi_token
*tokens_cur
;
200 struct tgsi_token
*tokens_end
;
201 struct tgsi_header
*header
;
202 unsigned processor
: 4;
203 int implied_array_size
: 5;
206 static void report_error( struct translate_ctx
*ctx
, const char *msg
)
210 const char *itr
= ctx
->text
;
212 while (itr
!= ctx
->cur
) {
221 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg
, line
, column
);
224 /* Parse shader header.
225 * Return TRUE for one of the following headers.
230 static boolean
parse_header( struct translate_ctx
*ctx
)
234 if (str_match_no_case( &ctx
->cur
, "FRAG" ))
235 processor
= TGSI_PROCESSOR_FRAGMENT
;
236 else if (str_match_no_case( &ctx
->cur
, "VERT" ))
237 processor
= TGSI_PROCESSOR_VERTEX
;
238 else if (str_match_no_case( &ctx
->cur
, "GEOM" ))
239 processor
= TGSI_PROCESSOR_GEOMETRY
;
241 report_error( ctx
, "Unknown header" );
245 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
247 ctx
->header
= (struct tgsi_header
*) ctx
->tokens_cur
++;
248 *ctx
->header
= tgsi_build_header();
250 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
252 *(struct tgsi_processor
*) ctx
->tokens_cur
++ = tgsi_build_processor( processor
, ctx
->header
);
253 ctx
->processor
= processor
;
258 static boolean
parse_label( struct translate_ctx
*ctx
, uint
*val
)
260 const char *cur
= ctx
->cur
;
262 if (parse_uint( &cur
, val
)) {
263 eat_opt_white( &cur
);
273 static const char *file_names
[TGSI_FILE_COUNT
] =
291 parse_file( const char **pcur
, uint
*file
)
295 for (i
= 0; i
< TGSI_FILE_COUNT
; i
++) {
296 const char *cur
= *pcur
;
298 if (str_match_no_case( &cur
, file_names
[i
] )) {
299 if (!is_digit_alpha_underscore( cur
)) {
311 struct translate_ctx
*ctx
,
317 eat_opt_white( &cur
);
320 *writemask
= TGSI_WRITEMASK_NONE
;
321 eat_opt_white( &cur
);
322 if (uprcase( *cur
) == 'X') {
324 *writemask
|= TGSI_WRITEMASK_X
;
326 if (uprcase( *cur
) == 'Y') {
328 *writemask
|= TGSI_WRITEMASK_Y
;
330 if (uprcase( *cur
) == 'Z') {
332 *writemask
|= TGSI_WRITEMASK_Z
;
334 if (uprcase( *cur
) == 'W') {
336 *writemask
|= TGSI_WRITEMASK_W
;
339 if (*writemask
== TGSI_WRITEMASK_NONE
) {
340 report_error( ctx
, "Writemask expected" );
347 *writemask
= TGSI_WRITEMASK_XYZW
;
353 /* <register_file_bracket> ::= <file> `['
356 parse_register_file_bracket(
357 struct translate_ctx
*ctx
,
360 if (!parse_file( &ctx
->cur
, file
)) {
361 report_error( ctx
, "Unknown register file" );
364 eat_opt_white( &ctx
->cur
);
365 if (*ctx
->cur
!= '[') {
366 report_error( ctx
, "Expected `['" );
373 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
376 parse_register_file_bracket_index(
377 struct translate_ctx
*ctx
,
383 if (!parse_register_file_bracket( ctx
, file
))
385 eat_opt_white( &ctx
->cur
);
386 if (!parse_uint( &ctx
->cur
, &uindex
)) {
387 report_error( ctx
, "Expected literal unsigned integer" );
390 *index
= (int) uindex
;
394 /* Parse simple 1d register operand.
395 * <register_dst> ::= <register_file_bracket_index> `]'
398 parse_register_1d(struct translate_ctx
*ctx
,
402 if (!parse_register_file_bracket_index( ctx
, file
, index
))
404 eat_opt_white( &ctx
->cur
);
405 if (*ctx
->cur
!= ']') {
406 report_error( ctx
, "Expected `]'" );
413 struct parsed_bracket
{
423 parse_register_bracket(
424 struct translate_ctx
*ctx
,
425 struct parsed_bracket
*brackets
)
430 memset(brackets
, 0, sizeof(struct parsed_bracket
));
432 eat_opt_white( &ctx
->cur
);
435 if (parse_file( &cur
, &brackets
->ind_file
)) {
436 if (!parse_register_1d( ctx
, &brackets
->ind_file
,
437 &brackets
->ind_index
))
439 eat_opt_white( &ctx
->cur
);
441 if (*ctx
->cur
== '.') {
443 eat_opt_white(&ctx
->cur
);
445 switch (uprcase(*ctx
->cur
)) {
447 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
450 brackets
->ind_comp
= TGSI_SWIZZLE_Y
;
453 brackets
->ind_comp
= TGSI_SWIZZLE_Z
;
456 brackets
->ind_comp
= TGSI_SWIZZLE_W
;
459 report_error(ctx
, "Expected indirect register swizzle component `x', `y', `z' or `w'");
463 eat_opt_white(&ctx
->cur
);
466 if (*ctx
->cur
== '+' || *ctx
->cur
== '-') {
469 negate
= *ctx
->cur
== '-';
471 eat_opt_white( &ctx
->cur
);
472 if (!parse_uint( &ctx
->cur
, &uindex
)) {
473 report_error( ctx
, "Expected literal unsigned integer" );
477 brackets
->index
= -(int) uindex
;
479 brackets
->index
= (int) uindex
;
486 if (!parse_uint( &ctx
->cur
, &uindex
)) {
487 report_error( ctx
, "Expected literal unsigned integer" );
490 brackets
->index
= (int) uindex
;
491 brackets
->ind_file
= TGSI_FILE_NULL
;
492 brackets
->ind_index
= 0;
494 eat_opt_white( &ctx
->cur
);
495 if (*ctx
->cur
!= ']') {
496 report_error( ctx
, "Expected `]'" );
504 parse_opt_register_src_bracket(
505 struct translate_ctx
*ctx
,
506 struct parsed_bracket
*brackets
,
507 int *parsed_brackets
)
509 const char *cur
= ctx
->cur
;
511 *parsed_brackets
= 0;
513 eat_opt_white( &cur
);
518 if (!parse_register_bracket(ctx
, brackets
))
521 *parsed_brackets
= 1;
528 /* Parse source register operand.
529 * <register_src> ::= <register_file_bracket_index> `]' |
530 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
531 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
532 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
536 struct translate_ctx
*ctx
,
538 struct parsed_bracket
*brackets
)
540 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
541 if (!parse_register_file_bracket( ctx
, file
))
543 if (!parse_register_bracket( ctx
, brackets
))
549 struct parsed_dcl_bracket
{
555 parse_register_dcl_bracket(
556 struct translate_ctx
*ctx
,
557 struct parsed_dcl_bracket
*bracket
)
560 memset(bracket
, 0, sizeof(struct parsed_dcl_bracket
));
562 eat_opt_white( &ctx
->cur
);
564 if (!parse_uint( &ctx
->cur
, &uindex
)) {
565 /* it can be an empty bracket [] which means its range
566 * is from 0 to some implied size */
567 if (ctx
->cur
[0] == ']' && ctx
->implied_array_size
!= 0) {
569 bracket
->last
= ctx
->implied_array_size
- 1;
572 report_error( ctx
, "Expected literal unsigned integer" );
575 bracket
->first
= uindex
;
577 eat_opt_white( &ctx
->cur
);
579 if (ctx
->cur
[0] == '.' && ctx
->cur
[1] == '.') {
583 eat_opt_white( &ctx
->cur
);
584 if (!parse_uint( &ctx
->cur
, &uindex
)) {
585 report_error( ctx
, "Expected literal integer" );
588 bracket
->last
= (int) uindex
;
589 eat_opt_white( &ctx
->cur
);
592 bracket
->last
= bracket
->first
;
596 if (*ctx
->cur
!= ']') {
597 report_error( ctx
, "Expected `]' or `..'" );
604 /* Parse register declaration.
605 * <register_dcl> ::= <register_file_bracket_index> `]' |
606 * <register_file_bracket_index> `..' <index> `]'
610 struct translate_ctx
*ctx
,
612 struct parsed_dcl_bracket
*brackets
,
619 if (!parse_register_file_bracket( ctx
, file
))
621 if (!parse_register_dcl_bracket( ctx
, &brackets
[0] ))
627 eat_opt_white( &cur
);
632 if (!parse_register_dcl_bracket( ctx
, &brackets
[1] ))
634 /* for geometry shader we don't really care about
635 * the first brackets it's always the size of the
636 * input primitive. so we want to declare just
637 * the index relevant to the semantics which is in
638 * the second bracket */
639 if (ctx
->processor
== TGSI_PROCESSOR_GEOMETRY
&& *file
== TGSI_FILE_INPUT
) {
640 brackets
[0] = brackets
[1];
651 /* Parse destination register operand.*/
654 struct translate_ctx
*ctx
,
656 struct parsed_bracket
*brackets
)
658 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
659 if (!parse_register_file_bracket( ctx
, file
))
661 if (!parse_register_bracket( ctx
, brackets
))
669 struct translate_ctx
*ctx
,
670 struct tgsi_full_dst_register
*dst
)
675 struct parsed_bracket bracket
[2];
676 int parsed_opt_brackets
;
678 if (!parse_register_dst( ctx
, &file
, &bracket
[0] ))
680 if (!parse_opt_register_src_bracket(ctx
, &bracket
[1], &parsed_opt_brackets
))
684 eat_opt_white( &cur
);
686 if (!parse_opt_writemask( ctx
, &writemask
))
689 dst
->Register
.File
= file
;
690 if (parsed_opt_brackets
) {
691 dst
->Register
.Dimension
= 1;
692 dst
->Dimension
.Indirect
= 0;
693 dst
->Dimension
.Dimension
= 0;
694 dst
->Dimension
.Index
= bracket
[0].index
;
695 bracket
[0] = bracket
[1];
697 dst
->Register
.Index
= bracket
[0].index
;
698 dst
->Register
.WriteMask
= writemask
;
699 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
700 dst
->Register
.Indirect
= 1;
701 dst
->Indirect
.File
= bracket
[0].ind_file
;
702 dst
->Indirect
.Index
= bracket
[0].ind_index
;
703 dst
->Indirect
.SwizzleX
= bracket
[0].ind_comp
;
704 dst
->Indirect
.SwizzleY
= bracket
[0].ind_comp
;
705 dst
->Indirect
.SwizzleZ
= bracket
[0].ind_comp
;
706 dst
->Indirect
.SwizzleW
= bracket
[0].ind_comp
;
712 parse_optional_swizzle(
713 struct translate_ctx
*ctx
,
715 boolean
*parsed_swizzle
)
717 const char *cur
= ctx
->cur
;
719 *parsed_swizzle
= FALSE
;
721 eat_opt_white( &cur
);
726 eat_opt_white( &cur
);
727 for (i
= 0; i
< 4; i
++) {
728 if (uprcase( *cur
) == 'X')
729 swizzle
[i
] = TGSI_SWIZZLE_X
;
730 else if (uprcase( *cur
) == 'Y')
731 swizzle
[i
] = TGSI_SWIZZLE_Y
;
732 else if (uprcase( *cur
) == 'Z')
733 swizzle
[i
] = TGSI_SWIZZLE_Z
;
734 else if (uprcase( *cur
) == 'W')
735 swizzle
[i
] = TGSI_SWIZZLE_W
;
737 report_error( ctx
, "Expected register swizzle component `x', `y', `z' or `w'" );
742 *parsed_swizzle
= TRUE
;
750 struct translate_ctx
*ctx
,
751 struct tgsi_full_src_register
*src
)
755 boolean parsed_swizzle
;
756 struct parsed_bracket bracket
[2];
757 int parsed_opt_brackets
;
759 if (*ctx
->cur
== '-') {
761 eat_opt_white( &ctx
->cur
);
762 src
->Register
.Negate
= 1;
765 if (*ctx
->cur
== '|') {
767 eat_opt_white( &ctx
->cur
);
768 src
->Register
.Absolute
= 1;
771 if (!parse_register_src(ctx
, &file
, &bracket
[0]))
773 if (!parse_opt_register_src_bracket(ctx
, &bracket
[1], &parsed_opt_brackets
))
776 src
->Register
.File
= file
;
777 if (parsed_opt_brackets
) {
778 src
->Register
.Dimension
= 1;
779 src
->Dimension
.Indirect
= 0;
780 src
->Dimension
.Dimension
= 0;
781 src
->Dimension
.Index
= bracket
[0].index
;
782 bracket
[0] = bracket
[1];
784 src
->Register
.Index
= bracket
[0].index
;
785 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
786 src
->Register
.Indirect
= 1;
787 src
->Indirect
.File
= bracket
[0].ind_file
;
788 src
->Indirect
.Index
= bracket
[0].ind_index
;
789 src
->Indirect
.SwizzleX
= bracket
[0].ind_comp
;
790 src
->Indirect
.SwizzleY
= bracket
[0].ind_comp
;
791 src
->Indirect
.SwizzleZ
= bracket
[0].ind_comp
;
792 src
->Indirect
.SwizzleW
= bracket
[0].ind_comp
;
795 /* Parse optional swizzle.
797 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
)) {
798 if (parsed_swizzle
) {
799 src
->Register
.SwizzleX
= swizzle
[0];
800 src
->Register
.SwizzleY
= swizzle
[1];
801 src
->Register
.SwizzleZ
= swizzle
[2];
802 src
->Register
.SwizzleW
= swizzle
[3];
806 if (src
->Register
.Absolute
) {
807 eat_opt_white( &ctx
->cur
);
808 if (*ctx
->cur
!= '|') {
809 report_error( ctx
, "Expected `|'" );
819 static const char *texture_names
[TGSI_TEXTURE_COUNT
] =
836 static const char *type_names
[] =
846 match_inst_mnemonic(const char **pcur
,
847 const struct tgsi_opcode_info
*info
)
849 if (str_match_no_case(pcur
, info
->mnemonic
)) {
857 struct translate_ctx
*ctx
,
861 uint saturate
= TGSI_SAT_NONE
;
862 const struct tgsi_opcode_info
*info
;
863 struct tgsi_full_instruction inst
;
866 inst
= tgsi_default_full_instruction();
870 eat_opt_white( &ctx
->cur
);
871 if (*ctx
->cur
== '(') {
875 boolean parsed_swizzle
;
877 inst
.Instruction
.Predicate
= 1;
880 if (*ctx
->cur
== '!') {
882 inst
.Predicate
.Negate
= 1;
885 if (!parse_register_1d( ctx
, &file
, &index
))
888 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
)) {
889 if (parsed_swizzle
) {
890 inst
.Predicate
.SwizzleX
= swizzle
[0];
891 inst
.Predicate
.SwizzleY
= swizzle
[1];
892 inst
.Predicate
.SwizzleZ
= swizzle
[2];
893 inst
.Predicate
.SwizzleW
= swizzle
[3];
897 if (*ctx
->cur
!= ')') {
898 report_error( ctx
, "Expected `)'" );
905 /* Parse instruction name.
907 eat_opt_white( &ctx
->cur
);
908 for (i
= 0; i
< TGSI_OPCODE_LAST
; i
++) {
909 const char *cur
= ctx
->cur
;
911 info
= tgsi_get_opcode_info( i
);
912 if (match_inst_mnemonic(&cur
, info
)) {
913 if (str_match_no_case( &cur
, "_SATNV" ))
914 saturate
= TGSI_SAT_MINUS_PLUS_ONE
;
915 else if (str_match_no_case( &cur
, "_SAT" ))
916 saturate
= TGSI_SAT_ZERO_ONE
;
918 if (info
->num_dst
+ info
->num_src
+ info
->is_tex
== 0) {
919 if (!is_digit_alpha_underscore( cur
)) {
924 else if (*cur
== '\0' || eat_white( &cur
)) {
930 if (i
== TGSI_OPCODE_LAST
) {
932 report_error( ctx
, "Unknown opcode" );
934 report_error( ctx
, "Expected `DCL', `IMM' or a label" );
938 inst
.Instruction
.Opcode
= i
;
939 inst
.Instruction
.Saturate
= saturate
;
940 inst
.Instruction
.NumDstRegs
= info
->num_dst
;
941 inst
.Instruction
.NumSrcRegs
= info
->num_src
;
943 /* Parse instruction operands.
945 for (i
= 0; i
< info
->num_dst
+ info
->num_src
+ info
->is_tex
; i
++) {
947 eat_opt_white( &ctx
->cur
);
948 if (*ctx
->cur
!= ',') {
949 report_error( ctx
, "Expected `,'" );
953 eat_opt_white( &ctx
->cur
);
956 if (i
< info
->num_dst
) {
957 if (!parse_dst_operand( ctx
, &inst
.Dst
[i
] ))
960 else if (i
< info
->num_dst
+ info
->num_src
) {
961 if (!parse_src_operand( ctx
, &inst
.Src
[i
- info
->num_dst
] ))
967 for (j
= 0; j
< TGSI_TEXTURE_COUNT
; j
++) {
968 if (str_match_no_case( &ctx
->cur
, texture_names
[j
] )) {
969 if (!is_digit_alpha_underscore( ctx
->cur
)) {
970 inst
.Instruction
.Texture
= 1;
971 inst
.Texture
.Texture
= j
;
976 if (j
== TGSI_TEXTURE_COUNT
) {
977 report_error( ctx
, "Expected texture target" );
983 if (info
->is_branch
) {
986 eat_opt_white( &ctx
->cur
);
987 if (*ctx
->cur
!= ':') {
988 report_error( ctx
, "Expected `:'" );
992 eat_opt_white( &ctx
->cur
);
993 if (!parse_uint( &ctx
->cur
, &target
)) {
994 report_error( ctx
, "Expected a label" );
997 inst
.Instruction
.Label
= 1;
998 inst
.Label
.Label
= target
;
1001 advance
= tgsi_build_full_instruction(
1005 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1008 ctx
->tokens_cur
+= advance
;
1013 static const char *semantic_names
[TGSI_SEMANTIC_COUNT
] =
1030 static const char *interpolate_names
[TGSI_INTERPOLATE_COUNT
] =
1038 /* parses a 4-touple of the form {x, y, z, w}
1039 * where x, y, z, w are numbers */
1040 static boolean
parse_immediate_data(struct translate_ctx
*ctx
,
1045 eat_opt_white( &ctx
->cur
);
1046 if (*ctx
->cur
!= '{') {
1047 report_error( ctx
, "Expected `{'" );
1051 for (i
= 0; i
< 4; i
++) {
1052 eat_opt_white( &ctx
->cur
);
1054 if (*ctx
->cur
!= ',') {
1055 report_error( ctx
, "Expected `,'" );
1059 eat_opt_white( &ctx
->cur
);
1061 if (!parse_float( &ctx
->cur
, &values
[i
] )) {
1062 report_error( ctx
, "Expected literal floating point" );
1066 eat_opt_white( &ctx
->cur
);
1067 if (*ctx
->cur
!= '}') {
1068 report_error( ctx
, "Expected `}'" );
1076 static boolean
parse_declaration( struct translate_ctx
*ctx
)
1078 struct tgsi_full_declaration decl
;
1080 struct parsed_dcl_bracket brackets
[2];
1085 boolean is_vs_input
;
1086 boolean is_imm_array
;
1088 assert(Elements(semantic_names
) == TGSI_SEMANTIC_COUNT
);
1089 assert(Elements(interpolate_names
) == TGSI_INTERPOLATE_COUNT
);
1091 if (!eat_white( &ctx
->cur
)) {
1092 report_error( ctx
, "Syntax error" );
1095 if (!parse_register_dcl( ctx
, &file
, brackets
, &num_brackets
))
1097 if (!parse_opt_writemask( ctx
, &writemask
))
1100 decl
= tgsi_default_full_declaration();
1101 decl
.Declaration
.File
= file
;
1102 decl
.Declaration
.UsageMask
= writemask
;
1104 if (num_brackets
== 1) {
1105 decl
.Range
.First
= brackets
[0].first
;
1106 decl
.Range
.Last
= brackets
[0].last
;
1108 decl
.Range
.First
= brackets
[1].first
;
1109 decl
.Range
.Last
= brackets
[1].last
;
1111 decl
.Declaration
.Dimension
= 1;
1112 decl
.Dim
.Index2D
= brackets
[0].first
;
1115 is_vs_input
= (file
== TGSI_FILE_INPUT
&&
1116 ctx
->processor
== TGSI_PROCESSOR_VERTEX
);
1117 is_imm_array
= (file
== TGSI_FILE_IMMEDIATE_ARRAY
);
1120 eat_opt_white( &cur
);
1121 if (*cur
== ',' && !is_vs_input
) {
1125 eat_opt_white( &cur
);
1126 if (file
== TGSI_FILE_RESOURCE
) {
1127 for (i
= 0; i
< TGSI_TEXTURE_COUNT
; i
++) {
1128 if (str_match_no_case(&cur
, texture_names
[i
])) {
1129 if (!is_digit_alpha_underscore(cur
)) {
1130 decl
.Resource
.Resource
= i
;
1135 if (i
== TGSI_TEXTURE_COUNT
) {
1136 report_error(ctx
, "Expected texture target");
1139 eat_opt_white( &cur
);
1141 report_error( ctx
, "Expected `,'" );
1145 eat_opt_white( &cur
);
1146 for (j
= 0; j
< 4; ++j
) {
1147 for (i
= 0; i
< PIPE_TYPE_COUNT
; ++i
) {
1148 if (str_match_no_case(&cur
, type_names
[i
])) {
1149 if (!is_digit_alpha_underscore(cur
)) {
1152 decl
.Resource
.ReturnTypeX
= i
;
1155 decl
.Resource
.ReturnTypeY
= i
;
1158 decl
.Resource
.ReturnTypeZ
= i
;
1161 decl
.Resource
.ReturnTypeW
= i
;
1170 if (i
== PIPE_TYPE_COUNT
) {
1171 if (j
== 0 || j
> 2) {
1172 report_error(ctx
, "Expected type name");
1177 const char *cur2
= cur
;
1178 eat_opt_white( &cur2
);
1181 eat_opt_white( &cur2
);
1189 decl
.Resource
.ReturnTypeY
=
1190 decl
.Resource
.ReturnTypeZ
=
1191 decl
.Resource
.ReturnTypeW
=
1192 decl
.Resource
.ReturnTypeX
;
1196 for (i
= 0; i
< TGSI_SEMANTIC_COUNT
; i
++) {
1197 if (str_match_no_case( &cur
, semantic_names
[i
] )) {
1198 const char *cur2
= cur
;
1201 if (is_digit_alpha_underscore( cur
))
1203 eat_opt_white( &cur2
);
1206 eat_opt_white( &cur2
);
1207 if (!parse_uint( &cur2
, &index
)) {
1208 report_error( ctx
, "Expected literal integer" );
1211 eat_opt_white( &cur2
);
1213 report_error( ctx
, "Expected `]'" );
1218 decl
.Semantic
.Index
= index
;
1223 decl
.Declaration
.Semantic
= 1;
1224 decl
.Semantic
.Name
= i
;
1231 } else if (is_imm_array
) {
1234 /* we have our immediate data */
1236 report_error( ctx
, "Immediate array without data" );
1242 decl
.ImmediateData
.u
=
1243 MALLOC(sizeof(union tgsi_immediate_data
) * 4 *
1244 (decl
.Range
.Last
+ 1));
1245 vals_itr
= (float*)decl
.ImmediateData
.u
;
1246 for (i
= 0; i
<= decl
.Range
.Last
; ++i
) {
1247 if (!parse_immediate_data(ctx
, vals_itr
)) {
1248 FREE(decl
.ImmediateData
.u
);
1252 eat_opt_white( &ctx
->cur
);
1253 if (*ctx
->cur
!= ',') {
1254 if (i
!= decl
.Range
.Last
) {
1255 report_error( ctx
, "Not enough data in immediate array!" );
1256 FREE(decl
.ImmediateData
.u
);
1262 eat_opt_white( &ctx
->cur
);
1263 if (*ctx
->cur
!= '}') {
1264 FREE(decl
.ImmediateData
.u
);
1265 report_error( ctx
, "Immediate array data missing closing '}'" );
1272 eat_opt_white( &cur
);
1273 if (*cur
== ',' && !is_vs_input
) {
1277 eat_opt_white( &cur
);
1278 for (i
= 0; i
< TGSI_INTERPOLATE_COUNT
; i
++) {
1279 if (str_match_no_case( &cur
, interpolate_names
[i
] )) {
1280 if (is_digit_alpha_underscore( cur
))
1282 decl
.Declaration
.Interpolate
= i
;
1288 if (i
== TGSI_INTERPOLATE_COUNT
) {
1289 report_error( ctx
, "Expected semantic or interpolate attribute" );
1294 advance
= tgsi_build_full_declaration(
1298 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1301 FREE(decl
.ImmediateData
.u
);
1305 ctx
->tokens_cur
+= advance
;
1310 static boolean
parse_immediate( struct translate_ctx
*ctx
)
1312 struct tgsi_full_immediate imm
;
1316 if (!eat_white( &ctx
->cur
)) {
1317 report_error( ctx
, "Syntax error" );
1320 if (!str_match_no_case( &ctx
->cur
, "FLT32" ) ||
1321 is_digit_alpha_underscore( ctx
->cur
)) {
1322 report_error( ctx
, "Expected `FLT32'" );
1326 parse_immediate_data(ctx
, values
);
1328 imm
= tgsi_default_full_immediate();
1329 imm
.Immediate
.NrTokens
+= 4;
1330 imm
.Immediate
.DataType
= TGSI_IMM_FLOAT32
;
1331 imm
.u
[0].Float
= values
[0];
1332 imm
.u
[1].Float
= values
[1];
1333 imm
.u
[2].Float
= values
[2];
1334 imm
.u
[3].Float
= values
[3];
1336 advance
= tgsi_build_full_immediate(
1340 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1343 ctx
->tokens_cur
+= advance
;
1349 parse_primitive( const char **pcur
, uint
*primitive
)
1353 for (i
= 0; i
< PIPE_PRIM_MAX
; i
++) {
1354 const char *cur
= *pcur
;
1356 if (str_match_no_case( &cur
, tgsi_primitive_names
[i
])) {
1366 parse_fs_coord_origin( const char **pcur
, uint
*fs_coord_origin
)
1370 for (i
= 0; i
< Elements(tgsi_fs_coord_origin_names
); i
++) {
1371 const char *cur
= *pcur
;
1373 if (str_match_no_case( &cur
, tgsi_fs_coord_origin_names
[i
])) {
1374 *fs_coord_origin
= i
;
1383 parse_fs_coord_pixel_center( const char **pcur
, uint
*fs_coord_pixel_center
)
1387 for (i
= 0; i
< Elements(tgsi_fs_coord_pixel_center_names
); i
++) {
1388 const char *cur
= *pcur
;
1390 if (str_match_no_case( &cur
, tgsi_fs_coord_pixel_center_names
[i
])) {
1391 *fs_coord_pixel_center
= i
;
1400 static boolean
parse_property( struct translate_ctx
*ctx
)
1402 struct tgsi_full_property prop
;
1408 if (!eat_white( &ctx
->cur
)) {
1409 report_error( ctx
, "Syntax error" );
1412 if (!parse_identifier( &ctx
->cur
, id
)) {
1413 report_error( ctx
, "Syntax error" );
1416 for (property_name
= 0; property_name
< TGSI_PROPERTY_COUNT
;
1418 if (streq_nocase_uprcase(tgsi_property_names
[property_name
], id
)) {
1422 if (property_name
>= TGSI_PROPERTY_COUNT
) {
1423 debug_printf( "\nError: Unknown property : '%s'", id
);
1427 eat_opt_white( &ctx
->cur
);
1428 switch(property_name
) {
1429 case TGSI_PROPERTY_GS_INPUT_PRIM
:
1430 case TGSI_PROPERTY_GS_OUTPUT_PRIM
:
1431 if (!parse_primitive(&ctx
->cur
, &values
[0] )) {
1432 report_error( ctx
, "Unknown primitive name as property!" );
1435 if (property_name
== TGSI_PROPERTY_GS_INPUT_PRIM
&&
1436 ctx
->processor
== TGSI_PROCESSOR_GEOMETRY
) {
1437 ctx
->implied_array_size
= u_vertices_per_prim(values
[0]);
1440 case TGSI_PROPERTY_FS_COORD_ORIGIN
:
1441 if (!parse_fs_coord_origin(&ctx
->cur
, &values
[0] )) {
1442 report_error( ctx
, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1446 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER
:
1447 if (!parse_fs_coord_pixel_center(&ctx
->cur
, &values
[0] )) {
1448 report_error( ctx
, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1452 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS
:
1454 if (!parse_uint(&ctx
->cur
, &values
[0] )) {
1455 report_error( ctx
, "Expected unsigned integer as property!" );
1460 prop
= tgsi_default_full_property();
1461 prop
.Property
.PropertyName
= property_name
;
1462 prop
.Property
.NrTokens
+= 1;
1463 prop
.u
[0].Data
= values
[0];
1465 advance
= tgsi_build_full_property(
1469 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1472 ctx
->tokens_cur
+= advance
;
1478 static boolean
translate( struct translate_ctx
*ctx
)
1480 eat_opt_white( &ctx
->cur
);
1481 if (!parse_header( ctx
))
1484 while (*ctx
->cur
!= '\0') {
1486 if (!eat_white( &ctx
->cur
)) {
1487 report_error( ctx
, "Syntax error" );
1491 if (*ctx
->cur
== '\0')
1493 if (parse_label( ctx
, &label_val
)) {
1494 if (!parse_instruction( ctx
, TRUE
))
1497 else if (str_match_no_case( &ctx
->cur
, "DCL" )) {
1498 if (!parse_declaration( ctx
))
1501 else if (str_match_no_case( &ctx
->cur
, "IMM" )) {
1502 if (!parse_immediate( ctx
))
1505 else if (str_match_no_case( &ctx
->cur
, "PROPERTY" )) {
1506 if (!parse_property( ctx
))
1509 else if (!parse_instruction( ctx
, FALSE
)) {
1518 tgsi_text_translate(
1520 struct tgsi_token
*tokens
,
1523 struct translate_ctx ctx
;
1527 ctx
.tokens
= tokens
;
1528 ctx
.tokens_cur
= tokens
;
1529 ctx
.tokens_end
= tokens
+ num_tokens
;
1531 if (!translate( &ctx
))
1534 return tgsi_sanity_check( tokens
);