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 "pipe/p_inlines.h"
33 #include "tgsi_text.h"
34 #include "tgsi_build.h"
35 #include "tgsi_info.h"
36 #include "tgsi_parse.h"
37 #include "tgsi_sanity.h"
38 #include "tgsi_util.h"
40 static boolean
is_alpha_underscore( const char *cur
)
43 (*cur
>= 'a' && *cur
<= 'z') ||
44 (*cur
>= 'A' && *cur
<= 'Z') ||
48 static boolean
is_digit( const char *cur
)
50 return *cur
>= '0' && *cur
<= '9';
53 static boolean
is_digit_alpha_underscore( const char *cur
)
55 return is_digit( cur
) || is_alpha_underscore( cur
);
58 static boolean
uprcase( char c
)
60 if (c
>= 'a' && c
<= 'z')
61 return c
+= 'A' - 'a';
66 * Ignore case of str1 and assume str1 is already uppercase.
67 * Return TRUE iff str1 and str2 are equal.
70 streq_nocase_uprcase(const char *str1
,
73 while (*str1
&& *str2
) {
74 if (*str1
!= uprcase(*str2
))
82 static boolean
str_match_no_case( const char **pcur
, const char *str
)
84 const char *cur
= *pcur
;
86 while (*str
!= '\0' && *str
== uprcase( *cur
)) {
97 /* Eat zero or more whitespaces.
99 static void eat_opt_white( const char **pcur
)
101 while (**pcur
== ' ' || **pcur
== '\t' || **pcur
== '\n')
105 /* Eat one or more whitespaces.
106 * Return TRUE if at least one whitespace eaten.
108 static boolean
eat_white( const char **pcur
)
110 const char *cur
= *pcur
;
112 eat_opt_white( pcur
);
116 /* Parse unsigned integer.
117 * No checks for overflow.
119 static boolean
parse_uint( const char **pcur
, uint
*val
)
121 const char *cur
= *pcur
;
123 if (is_digit( cur
)) {
125 while (is_digit( cur
))
126 *val
= *val
* 10 + *cur
++ - '0';
133 static boolean
parse_identifier( const char **pcur
, char *ret
)
135 const char *cur
= *pcur
;
137 if (is_alpha_underscore( cur
)) {
139 while (is_alpha_underscore( cur
))
147 /* Parse floating point.
149 static boolean
parse_float( const char **pcur
, float *val
)
151 const char *cur
= *pcur
;
152 boolean integral_part
= FALSE
;
153 boolean fractional_part
= FALSE
;
155 *val
= (float) atof( cur
);
157 if (*cur
== '-' || *cur
== '+')
159 if (is_digit( cur
)) {
161 integral_part
= TRUE
;
162 while (is_digit( cur
))
167 if (is_digit( cur
)) {
169 fractional_part
= TRUE
;
170 while (is_digit( cur
))
174 if (!integral_part
&& !fractional_part
)
176 if (uprcase( *cur
) == 'E') {
178 if (*cur
== '-' || *cur
== '+')
180 if (is_digit( cur
)) {
182 while (is_digit( cur
))
196 struct tgsi_token
*tokens
;
197 struct tgsi_token
*tokens_cur
;
198 struct tgsi_token
*tokens_end
;
199 struct tgsi_header
*header
;
200 unsigned processor
: 4;
201 int implied_array_size
: 5;
204 static void report_error( struct translate_ctx
*ctx
, const char *msg
)
208 const char *itr
= ctx
->text
;
210 while (itr
!= ctx
->cur
) {
219 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg
, line
, column
);
222 /* Parse shader header.
223 * Return TRUE for one of the following headers.
228 static boolean
parse_header( struct translate_ctx
*ctx
)
232 if (str_match_no_case( &ctx
->cur
, "FRAG" ))
233 processor
= TGSI_PROCESSOR_FRAGMENT
;
234 else if (str_match_no_case( &ctx
->cur
, "VERT" ))
235 processor
= TGSI_PROCESSOR_VERTEX
;
236 else if (str_match_no_case( &ctx
->cur
, "GEOM" ))
237 processor
= TGSI_PROCESSOR_GEOMETRY
;
239 report_error( ctx
, "Unknown header" );
243 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
245 ctx
->header
= (struct tgsi_header
*) ctx
->tokens_cur
++;
246 *ctx
->header
= tgsi_build_header();
248 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
250 *(struct tgsi_processor
*) ctx
->tokens_cur
++ = tgsi_build_processor( processor
, ctx
->header
);
251 ctx
->processor
= processor
;
256 static boolean
parse_label( struct translate_ctx
*ctx
, uint
*val
)
258 const char *cur
= ctx
->cur
;
260 if (parse_uint( &cur
, val
)) {
261 eat_opt_white( &cur
);
271 static const char *file_names
[TGSI_FILE_COUNT
] =
287 parse_file( const char **pcur
, uint
*file
)
291 for (i
= 0; i
< TGSI_FILE_COUNT
; i
++) {
292 const char *cur
= *pcur
;
294 if (str_match_no_case( &cur
, file_names
[i
] )) {
295 if (!is_digit_alpha_underscore( cur
)) {
307 struct translate_ctx
*ctx
,
313 eat_opt_white( &cur
);
316 *writemask
= TGSI_WRITEMASK_NONE
;
317 eat_opt_white( &cur
);
318 if (uprcase( *cur
) == 'X') {
320 *writemask
|= TGSI_WRITEMASK_X
;
322 if (uprcase( *cur
) == 'Y') {
324 *writemask
|= TGSI_WRITEMASK_Y
;
326 if (uprcase( *cur
) == 'Z') {
328 *writemask
|= TGSI_WRITEMASK_Z
;
330 if (uprcase( *cur
) == 'W') {
332 *writemask
|= TGSI_WRITEMASK_W
;
335 if (*writemask
== TGSI_WRITEMASK_NONE
) {
336 report_error( ctx
, "Writemask expected" );
343 *writemask
= TGSI_WRITEMASK_XYZW
;
349 parse_register_dst( struct translate_ctx
*ctx
,
353 struct parsed_src_bracket
{
363 parse_register_src_bracket(
364 struct translate_ctx
*ctx
,
365 struct parsed_src_bracket
*brackets
)
370 memset(brackets
, 0, sizeof(struct parsed_src_bracket
));
372 eat_opt_white( &ctx
->cur
);
375 if (parse_file( &cur
, &brackets
->ind_file
)) {
376 if (!parse_register_dst( ctx
, &brackets
->ind_file
,
377 &brackets
->ind_index
))
379 eat_opt_white( &ctx
->cur
);
381 if (*ctx
->cur
== '.') {
383 eat_opt_white(&ctx
->cur
);
385 switch (uprcase(*ctx
->cur
)) {
387 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
390 brackets
->ind_comp
= TGSI_SWIZZLE_Y
;
393 brackets
->ind_comp
= TGSI_SWIZZLE_Z
;
396 brackets
->ind_comp
= TGSI_SWIZZLE_W
;
399 report_error(ctx
, "Expected indirect register swizzle component `x', `y', `z' or `w'");
403 eat_opt_white(&ctx
->cur
);
406 if (*ctx
->cur
== '+' || *ctx
->cur
== '-') {
409 negate
= *ctx
->cur
== '-';
411 eat_opt_white( &ctx
->cur
);
412 if (!parse_uint( &ctx
->cur
, &uindex
)) {
413 report_error( ctx
, "Expected literal unsigned integer" );
417 brackets
->index
= -(int) uindex
;
419 brackets
->index
= (int) uindex
;
426 if (!parse_uint( &ctx
->cur
, &uindex
)) {
427 report_error( ctx
, "Expected literal unsigned integer" );
430 brackets
->index
= (int) uindex
;
431 brackets
->ind_file
= TGSI_FILE_NULL
;
432 brackets
->ind_index
= 0;
434 eat_opt_white( &ctx
->cur
);
435 if (*ctx
->cur
!= ']') {
436 report_error( ctx
, "Expected `]'" );
444 parse_opt_register_src_bracket(
445 struct translate_ctx
*ctx
,
446 struct parsed_src_bracket
*brackets
,
447 int *parsed_brackets
)
449 const char *cur
= ctx
->cur
;
451 *parsed_brackets
= 0;
453 eat_opt_white( &cur
);
458 if (!parse_register_src_bracket(ctx
, brackets
))
461 *parsed_brackets
= 1;
467 /* <register_file_bracket> ::= <file> `['
470 parse_register_file_bracket(
471 struct translate_ctx
*ctx
,
474 if (!parse_file( &ctx
->cur
, file
)) {
475 report_error( ctx
, "Unknown register file" );
478 eat_opt_white( &ctx
->cur
);
479 if (*ctx
->cur
!= '[') {
480 report_error( ctx
, "Expected `['" );
487 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
490 parse_register_file_bracket_index(
491 struct translate_ctx
*ctx
,
497 if (!parse_register_file_bracket( ctx
, file
))
499 eat_opt_white( &ctx
->cur
);
500 if (!parse_uint( &ctx
->cur
, &uindex
)) {
501 report_error( ctx
, "Expected literal unsigned integer" );
504 *index
= (int) uindex
;
508 /* Parse source register operand.
509 * <register_src> ::= <register_file_bracket_index> `]' |
510 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
511 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
512 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
516 struct translate_ctx
*ctx
,
518 struct parsed_src_bracket
*brackets
)
521 brackets
->ind_comp
= TGSI_SWIZZLE_X
;
522 if (!parse_register_file_bracket( ctx
, file
))
524 if (!parse_register_src_bracket( ctx
, brackets
))
530 struct parsed_dcl_bracket
{
536 parse_register_dcl_bracket(
537 struct translate_ctx
*ctx
,
538 struct parsed_dcl_bracket
*bracket
)
541 memset(bracket
, 0, sizeof(struct parsed_dcl_bracket
));
543 eat_opt_white( &ctx
->cur
);
545 if (!parse_uint( &ctx
->cur
, &uindex
)) {
546 /* it can be an empty bracket [] which means its range
547 * is from 0 to some implied size */
548 if (ctx
->cur
[0] == ']' && ctx
->implied_array_size
!= 0) {
550 bracket
->last
= ctx
->implied_array_size
- 1;
553 report_error( ctx
, "Expected literal unsigned integer" );
556 bracket
->first
= (int) uindex
;
558 eat_opt_white( &ctx
->cur
);
560 if (ctx
->cur
[0] == '.' && ctx
->cur
[1] == '.') {
564 eat_opt_white( &ctx
->cur
);
565 if (!parse_uint( &ctx
->cur
, &uindex
)) {
566 report_error( ctx
, "Expected literal integer" );
569 bracket
->last
= (int) uindex
;
570 eat_opt_white( &ctx
->cur
);
573 bracket
->last
= bracket
->first
;
577 if (*ctx
->cur
!= ']') {
578 report_error( ctx
, "Expected `]' or `..'" );
585 /* Parse register declaration.
586 * <register_dcl> ::= <register_file_bracket_index> `]' |
587 * <register_file_bracket_index> `..' <index> `]'
591 struct translate_ctx
*ctx
,
593 struct parsed_dcl_bracket
*brackets
,
600 if (!parse_register_file_bracket( ctx
, file
))
602 if (!parse_register_dcl_bracket( ctx
, &brackets
[0] ))
608 eat_opt_white( &cur
);
613 if (!parse_register_dcl_bracket( ctx
, &brackets
[1] ))
615 /* for geometry shader we don't really care about
616 * the first brackets it's always the size of the
617 * input primitive. so we want to declare just
618 * the index relevant to the semantics which is in
619 * the second bracket */
620 if (ctx
->processor
== TGSI_PROCESSOR_GEOMETRY
) {
621 brackets
[0] = brackets
[1];
630 /* Parse destination register operand.
631 * <register_dst> ::= <register_file_bracket_index> `]'
635 struct translate_ctx
*ctx
,
639 if (!parse_register_file_bracket_index( ctx
, file
, index
))
641 eat_opt_white( &ctx
->cur
);
642 if (*ctx
->cur
!= ']') {
643 report_error( ctx
, "Expected `]'" );
652 struct translate_ctx
*ctx
,
653 struct tgsi_full_dst_register
*dst
)
660 if (!parse_register_dst( ctx
, &file
, &index
))
664 eat_opt_white( &cur
);
666 if (!parse_opt_writemask( ctx
, &writemask
))
669 dst
->Register
.File
= file
;
670 dst
->Register
.Index
= index
;
671 dst
->Register
.WriteMask
= writemask
;
676 parse_optional_swizzle(
677 struct translate_ctx
*ctx
,
679 boolean
*parsed_swizzle
)
681 const char *cur
= ctx
->cur
;
683 *parsed_swizzle
= FALSE
;
685 eat_opt_white( &cur
);
690 eat_opt_white( &cur
);
691 for (i
= 0; i
< 4; i
++) {
692 if (uprcase( *cur
) == 'X')
693 swizzle
[i
] = TGSI_SWIZZLE_X
;
694 else if (uprcase( *cur
) == 'Y')
695 swizzle
[i
] = TGSI_SWIZZLE_Y
;
696 else if (uprcase( *cur
) == 'Z')
697 swizzle
[i
] = TGSI_SWIZZLE_Z
;
698 else if (uprcase( *cur
) == 'W')
699 swizzle
[i
] = TGSI_SWIZZLE_W
;
701 report_error( ctx
, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" );
706 *parsed_swizzle
= TRUE
;
714 struct translate_ctx
*ctx
,
715 struct tgsi_full_src_register
*src
)
719 boolean parsed_swizzle
;
720 struct parsed_src_bracket bracket
[2];
721 int parsed_opt_brackets
;
723 if (*ctx
->cur
== '-') {
725 eat_opt_white( &ctx
->cur
);
726 src
->Register
.Negate
= 1;
729 if (*ctx
->cur
== '|') {
731 eat_opt_white( &ctx
->cur
);
732 src
->Register
.Absolute
= 1;
735 if (!parse_register_src(ctx
, &file
, &bracket
[0]))
737 if (!parse_opt_register_src_bracket(ctx
, &bracket
[1], &parsed_opt_brackets
))
740 src
->Register
.File
= file
;
741 src
->Register
.Index
= bracket
[0].index
;
742 if (bracket
[0].ind_file
!= TGSI_FILE_NULL
) {
743 src
->Register
.Indirect
= 1;
744 src
->Indirect
.File
= bracket
[0].ind_file
;
745 src
->Indirect
.Index
= bracket
[0].ind_index
;
746 src
->Indirect
.SwizzleX
= bracket
[0].ind_comp
;
747 src
->Indirect
.SwizzleY
= bracket
[0].ind_comp
;
748 src
->Indirect
.SwizzleZ
= bracket
[0].ind_comp
;
749 src
->Indirect
.SwizzleW
= bracket
[0].ind_comp
;
751 if (parsed_opt_brackets
) {
752 src
->Register
.Dimension
= 1;
753 src
->Dimension
.Indirect
= 0;
754 src
->Dimension
.Dimension
= 0;
755 src
->Dimension
.Index
= bracket
[1].index
;
758 /* Parse optional swizzle.
760 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
)) {
761 if (parsed_swizzle
) {
762 src
->Register
.SwizzleX
= swizzle
[0];
763 src
->Register
.SwizzleY
= swizzle
[1];
764 src
->Register
.SwizzleZ
= swizzle
[2];
765 src
->Register
.SwizzleW
= swizzle
[3];
769 if (src
->Register
.Absolute
) {
770 eat_opt_white( &ctx
->cur
);
771 if (*ctx
->cur
!= '|') {
772 report_error( ctx
, "Expected `|'" );
782 static const char *texture_names
[TGSI_TEXTURE_COUNT
] =
796 match_inst_mnemonic(const char **pcur
,
797 const struct tgsi_opcode_info
*info
)
799 if (str_match_no_case(pcur
, info
->mnemonic
)) {
807 struct translate_ctx
*ctx
,
811 uint saturate
= TGSI_SAT_NONE
;
812 const struct tgsi_opcode_info
*info
;
813 struct tgsi_full_instruction inst
;
816 /* Parse instruction name.
818 eat_opt_white( &ctx
->cur
);
819 for (i
= 0; i
< TGSI_OPCODE_LAST
; i
++) {
820 const char *cur
= ctx
->cur
;
822 info
= tgsi_get_opcode_info( i
);
823 if (match_inst_mnemonic(&cur
, info
)) {
824 if (str_match_no_case( &cur
, "_SATNV" ))
825 saturate
= TGSI_SAT_MINUS_PLUS_ONE
;
826 else if (str_match_no_case( &cur
, "_SAT" ))
827 saturate
= TGSI_SAT_ZERO_ONE
;
829 if (info
->num_dst
+ info
->num_src
+ info
->is_tex
== 0) {
830 if (!is_digit_alpha_underscore( cur
)) {
835 else if (*cur
== '\0' || eat_white( &cur
)) {
841 if (i
== TGSI_OPCODE_LAST
) {
843 report_error( ctx
, "Unknown opcode" );
845 report_error( ctx
, "Expected `DCL', `IMM' or a label" );
849 inst
= tgsi_default_full_instruction();
850 inst
.Instruction
.Opcode
= i
;
851 inst
.Instruction
.Saturate
= saturate
;
852 inst
.Instruction
.NumDstRegs
= info
->num_dst
;
853 inst
.Instruction
.NumSrcRegs
= info
->num_src
;
855 /* Parse instruction operands.
857 for (i
= 0; i
< info
->num_dst
+ info
->num_src
+ info
->is_tex
; i
++) {
859 eat_opt_white( &ctx
->cur
);
860 if (*ctx
->cur
!= ',') {
861 report_error( ctx
, "Expected `,'" );
865 eat_opt_white( &ctx
->cur
);
868 if (i
< info
->num_dst
) {
869 if (!parse_dst_operand( ctx
, &inst
.Dst
[i
] ))
872 else if (i
< info
->num_dst
+ info
->num_src
) {
873 if (!parse_src_operand( ctx
, &inst
.Src
[i
- info
->num_dst
] ))
879 for (j
= 0; j
< TGSI_TEXTURE_COUNT
; j
++) {
880 if (str_match_no_case( &ctx
->cur
, texture_names
[j
] )) {
881 if (!is_digit_alpha_underscore( ctx
->cur
)) {
882 inst
.Instruction
.Texture
= 1;
883 inst
.Texture
.Texture
= j
;
888 if (j
== TGSI_TEXTURE_COUNT
) {
889 report_error( ctx
, "Expected texture target" );
895 if (info
->is_branch
) {
898 eat_opt_white( &ctx
->cur
);
899 if (*ctx
->cur
!= ':') {
900 report_error( ctx
, "Expected `:'" );
904 eat_opt_white( &ctx
->cur
);
905 if (!parse_uint( &ctx
->cur
, &target
)) {
906 report_error( ctx
, "Expected a label" );
909 inst
.Instruction
.Label
= 1;
910 inst
.Label
.Label
= target
;
913 advance
= tgsi_build_full_instruction(
917 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
920 ctx
->tokens_cur
+= advance
;
925 static const char *semantic_names
[TGSI_SEMANTIC_COUNT
] =
940 static const char *interpolate_names
[TGSI_INTERPOLATE_COUNT
] =
947 static boolean
parse_declaration( struct translate_ctx
*ctx
)
949 struct tgsi_full_declaration decl
;
951 struct parsed_dcl_bracket brackets
[2];
957 assert(Elements(semantic_names
) == TGSI_SEMANTIC_COUNT
);
958 assert(Elements(interpolate_names
) == TGSI_INTERPOLATE_COUNT
);
960 if (!eat_white( &ctx
->cur
)) {
961 report_error( ctx
, "Syntax error" );
964 if (!parse_register_dcl( ctx
, &file
, brackets
, &num_brackets
))
966 if (!parse_opt_writemask( ctx
, &writemask
))
969 decl
= tgsi_default_full_declaration();
970 decl
.Declaration
.File
= file
;
971 decl
.Declaration
.UsageMask
= writemask
;
972 decl
.Range
.First
= brackets
[0].first
;
973 decl
.Range
.Last
= brackets
[0].last
;
976 eat_opt_white( &cur
);
981 eat_opt_white( &cur
);
982 for (i
= 0; i
< TGSI_SEMANTIC_COUNT
; i
++) {
983 if (str_match_no_case( &cur
, semantic_names
[i
] )) {
984 const char *cur2
= cur
;
987 if (is_digit_alpha_underscore( cur
))
989 eat_opt_white( &cur2
);
992 eat_opt_white( &cur2
);
993 if (!parse_uint( &cur2
, &index
)) {
994 report_error( ctx
, "Expected literal integer" );
997 eat_opt_white( &cur2
);
999 report_error( ctx
, "Expected `]'" );
1004 decl
.Semantic
.Index
= index
;
1009 decl
.Declaration
.Semantic
= 1;
1010 decl
.Semantic
.Name
= i
;
1019 eat_opt_white( &cur
);
1024 eat_opt_white( &cur
);
1025 for (i
= 0; i
< TGSI_INTERPOLATE_COUNT
; i
++) {
1026 if (str_match_no_case( &cur
, interpolate_names
[i
] )) {
1027 if (is_digit_alpha_underscore( cur
))
1029 decl
.Declaration
.Interpolate
= i
;
1035 if (i
== TGSI_INTERPOLATE_COUNT
) {
1036 report_error( ctx
, "Expected semantic or interpolate attribute" );
1041 advance
= tgsi_build_full_declaration(
1045 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1048 ctx
->tokens_cur
+= advance
;
1053 static boolean
parse_immediate( struct translate_ctx
*ctx
)
1055 struct tgsi_full_immediate imm
;
1060 if (!eat_white( &ctx
->cur
)) {
1061 report_error( ctx
, "Syntax error" );
1064 if (!str_match_no_case( &ctx
->cur
, "FLT32" ) || is_digit_alpha_underscore( ctx
->cur
)) {
1065 report_error( ctx
, "Expected `FLT32'" );
1068 eat_opt_white( &ctx
->cur
);
1069 if (*ctx
->cur
!= '{') {
1070 report_error( ctx
, "Expected `{'" );
1074 for (i
= 0; i
< 4; i
++) {
1075 eat_opt_white( &ctx
->cur
);
1077 if (*ctx
->cur
!= ',') {
1078 report_error( ctx
, "Expected `,'" );
1082 eat_opt_white( &ctx
->cur
);
1084 if (!parse_float( &ctx
->cur
, &values
[i
] )) {
1085 report_error( ctx
, "Expected literal floating point" );
1089 eat_opt_white( &ctx
->cur
);
1090 if (*ctx
->cur
!= '}') {
1091 report_error( ctx
, "Expected `}'" );
1096 imm
= tgsi_default_full_immediate();
1097 imm
.Immediate
.NrTokens
+= 4;
1098 imm
.Immediate
.DataType
= TGSI_IMM_FLOAT32
;
1099 imm
.u
[0].Float
= values
[0];
1100 imm
.u
[1].Float
= values
[1];
1101 imm
.u
[2].Float
= values
[2];
1102 imm
.u
[3].Float
= values
[3];
1104 advance
= tgsi_build_full_immediate(
1108 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1111 ctx
->tokens_cur
+= advance
;
1116 static const char *property_names
[] =
1118 "GS_INPUT_PRIMITIVE",
1119 "GS_OUTPUT_PRIMITIVE",
1120 "GS_MAX_OUTPUT_VERTICES"
1123 static const char *primitive_names
[] =
1138 parse_primitive( const char **pcur
, uint
*primitive
)
1142 for (i
= 0; i
< PIPE_PRIM_MAX
; i
++) {
1143 const char *cur
= *pcur
;
1145 if (str_match_no_case( &cur
, primitive_names
[i
])) {
1155 static boolean
parse_property( struct translate_ctx
*ctx
)
1157 struct tgsi_full_property prop
;
1163 if (!eat_white( &ctx
->cur
)) {
1164 report_error( ctx
, "Syntax error" );
1167 if (!parse_identifier( &ctx
->cur
, id
)) {
1168 report_error( ctx
, "Syntax error" );
1171 for (property_name
= 0; property_name
< TGSI_PROPERTY_COUNT
;
1173 if (streq_nocase_uprcase(property_names
[property_name
], id
)) {
1177 if (property_name
>= TGSI_PROPERTY_COUNT
) {
1178 debug_printf( "\nError: Unknown property : '%s'", id
);
1182 eat_opt_white( &ctx
->cur
);
1183 switch(property_name
) {
1184 case TGSI_PROPERTY_GS_INPUT_PRIM
:
1185 case TGSI_PROPERTY_GS_OUTPUT_PRIM
:
1186 if (!parse_primitive(&ctx
->cur
, &values
[0] )) {
1187 report_error( ctx
, "Unknown primitive name as property!" );
1190 if (property_name
== TGSI_PROPERTY_GS_INPUT_PRIM
&&
1191 ctx
->processor
== TGSI_PROCESSOR_GEOMETRY
) {
1192 ctx
->implied_array_size
= u_vertices_per_prim(values
[0]);
1196 if (!parse_uint(&ctx
->cur
, &values
[0] )) {
1197 report_error( ctx
, "Expected unsigned integer as property!" );
1202 prop
= tgsi_default_full_property();
1203 prop
.Property
.PropertyName
= property_name
;
1204 prop
.Property
.NrTokens
+= 1;
1205 prop
.u
[0].Data
= values
[0];
1207 advance
= tgsi_build_full_property(
1211 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1214 ctx
->tokens_cur
+= advance
;
1220 static boolean
translate( struct translate_ctx
*ctx
)
1222 eat_opt_white( &ctx
->cur
);
1223 if (!parse_header( ctx
))
1226 while (*ctx
->cur
!= '\0') {
1228 if (!eat_white( &ctx
->cur
)) {
1229 report_error( ctx
, "Syntax error" );
1233 if (*ctx
->cur
== '\0')
1235 if (parse_label( ctx
, &label_val
)) {
1236 if (!parse_instruction( ctx
, TRUE
))
1239 else if (str_match_no_case( &ctx
->cur
, "DCL" )) {
1240 if (!parse_declaration( ctx
))
1243 else if (str_match_no_case( &ctx
->cur
, "IMM" )) {
1244 if (!parse_immediate( ctx
))
1247 else if (str_match_no_case( &ctx
->cur
, "PROPERTY" )) {
1248 if (!parse_property( ctx
))
1251 else if (!parse_instruction( ctx
, FALSE
)) {
1260 tgsi_text_translate(
1262 struct tgsi_token
*tokens
,
1265 struct translate_ctx ctx
;
1269 ctx
.tokens
= tokens
;
1270 ctx
.tokens_cur
= tokens
;
1271 ctx
.tokens_end
= tokens
+ num_tokens
;
1273 if (!translate( &ctx
))
1276 return tgsi_sanity_check( tokens
);