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 "pipe/p_defines.h"
31 #include "tgsi_text.h"
32 #include "tgsi_build.h"
33 #include "tgsi_info.h"
34 #include "tgsi_parse.h"
35 #include "tgsi_sanity.h"
36 #include "tgsi_util.h"
38 static boolean
is_alpha_underscore( const char *cur
)
41 (*cur
>= 'a' && *cur
<= 'z') ||
42 (*cur
>= 'A' && *cur
<= 'Z') ||
46 static boolean
is_digit( const char *cur
)
48 return *cur
>= '0' && *cur
<= '9';
51 static boolean
is_digit_alpha_underscore( const char *cur
)
53 return is_digit( cur
) || is_alpha_underscore( cur
);
56 static boolean
uprcase( char c
)
58 if (c
>= 'a' && c
<= 'z')
59 return c
+= 'A' - 'a';
64 * Ignore case of str1 and assume str2 is already uppercase.
65 * Return TRUE iff str1 and str2 are equal.
68 streq_nocase_uprcase(const char *str1
,
71 while (*str1
&& uprcase(*str1
) == *str2
) {
75 return *str1
== *str2
;
78 static boolean
str_match_no_case( const char **pcur
, const char *str
)
80 const char *cur
= *pcur
;
82 while (*str
!= '\0' && *str
== uprcase( *cur
)) {
93 /* Eat zero or more whitespaces.
95 static void eat_opt_white( const char **pcur
)
97 while (**pcur
== ' ' || **pcur
== '\t' || **pcur
== '\n')
101 /* Eat one or more whitespaces.
102 * Return TRUE if at least one whitespace eaten.
104 static boolean
eat_white( const char **pcur
)
106 const char *cur
= *pcur
;
108 eat_opt_white( pcur
);
112 /* Parse unsigned integer.
113 * No checks for overflow.
115 static boolean
parse_uint( const char **pcur
, uint
*val
)
117 const char *cur
= *pcur
;
119 if (is_digit( cur
)) {
121 while (is_digit( cur
))
122 *val
= *val
* 10 + *cur
++ - '0';
129 static boolean
parse_identifier( const char **pcur
, char *ret
)
131 const char *cur
= *pcur
;
133 if (is_alpha_underscore( cur
)) {
135 while (is_alpha_underscore( cur
))
143 /* Parse floating point.
145 static boolean
parse_float( const char **pcur
, float *val
)
147 const char *cur
= *pcur
;
148 boolean integral_part
= FALSE
;
149 boolean fractional_part
= FALSE
;
151 *val
= (float) atof( cur
);
153 if (*cur
== '-' || *cur
== '+')
155 if (is_digit( cur
)) {
157 integral_part
= TRUE
;
158 while (is_digit( cur
))
163 if (is_digit( cur
)) {
165 fractional_part
= TRUE
;
166 while (is_digit( cur
))
170 if (!integral_part
&& !fractional_part
)
172 if (uprcase( *cur
) == 'E') {
174 if (*cur
== '-' || *cur
== '+')
176 if (is_digit( cur
)) {
178 while (is_digit( cur
))
192 struct tgsi_token
*tokens
;
193 struct tgsi_token
*tokens_cur
;
194 struct tgsi_token
*tokens_end
;
195 struct tgsi_header
*header
;
198 static void report_error( struct translate_ctx
*ctx
, const char *msg
)
202 const char *itr
= ctx
->text
;
204 while (itr
!= ctx
->cur
) {
213 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg
, line
, column
);
216 /* Parse shader header.
217 * Return TRUE for one of the following headers.
222 static boolean
parse_header( struct translate_ctx
*ctx
)
226 if (str_match_no_case( &ctx
->cur
, "FRAG" ))
227 processor
= TGSI_PROCESSOR_FRAGMENT
;
228 else if (str_match_no_case( &ctx
->cur
, "VERT" ))
229 processor
= TGSI_PROCESSOR_VERTEX
;
230 else if (str_match_no_case( &ctx
->cur
, "GEOM" ))
231 processor
= TGSI_PROCESSOR_GEOMETRY
;
233 report_error( ctx
, "Unknown header" );
237 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
239 ctx
->header
= (struct tgsi_header
*) ctx
->tokens_cur
++;
240 *ctx
->header
= tgsi_build_header();
242 if (ctx
->tokens_cur
>= ctx
->tokens_end
)
244 *(struct tgsi_processor
*) ctx
->tokens_cur
++ = tgsi_build_processor( processor
, ctx
->header
);
249 static boolean
parse_label( struct translate_ctx
*ctx
, uint
*val
)
251 const char *cur
= ctx
->cur
;
253 if (parse_uint( &cur
, val
)) {
254 eat_opt_white( &cur
);
264 static const char *file_names
[TGSI_FILE_COUNT
] =
280 parse_file( const char **pcur
, uint
*file
)
284 for (i
= 0; i
< TGSI_FILE_COUNT
; i
++) {
285 const char *cur
= *pcur
;
287 if (str_match_no_case( &cur
, file_names
[i
] )) {
288 if (!is_digit_alpha_underscore( cur
)) {
300 struct translate_ctx
*ctx
,
306 eat_opt_white( &cur
);
309 *writemask
= TGSI_WRITEMASK_NONE
;
310 eat_opt_white( &cur
);
311 if (uprcase( *cur
) == 'X') {
313 *writemask
|= TGSI_WRITEMASK_X
;
315 if (uprcase( *cur
) == 'Y') {
317 *writemask
|= TGSI_WRITEMASK_Y
;
319 if (uprcase( *cur
) == 'Z') {
321 *writemask
|= TGSI_WRITEMASK_Z
;
323 if (uprcase( *cur
) == 'W') {
325 *writemask
|= TGSI_WRITEMASK_W
;
328 if (*writemask
== TGSI_WRITEMASK_NONE
) {
329 report_error( ctx
, "Writemask expected" );
336 *writemask
= TGSI_WRITEMASK_XYZW
;
341 /* <register_file_bracket> ::= <file> `['
344 parse_register_file_bracket(
345 struct translate_ctx
*ctx
,
348 if (!parse_file( &ctx
->cur
, file
)) {
349 report_error( ctx
, "Unknown register file" );
352 eat_opt_white( &ctx
->cur
);
353 if (*ctx
->cur
!= '[') {
354 report_error( ctx
, "Expected `['" );
361 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
364 parse_register_file_bracket_index(
365 struct translate_ctx
*ctx
,
371 if (!parse_register_file_bracket( ctx
, file
))
373 eat_opt_white( &ctx
->cur
);
374 if (!parse_uint( &ctx
->cur
, &uindex
)) {
375 report_error( ctx
, "Expected literal unsigned integer" );
378 *index
= (int) uindex
;
382 /* Parse destination register operand.
383 * <register_dst> ::= <register_file_bracket_index> `]'
387 struct translate_ctx
*ctx
,
391 if (!parse_register_file_bracket_index( ctx
, file
, index
))
393 eat_opt_white( &ctx
->cur
);
394 if (*ctx
->cur
!= ']') {
395 report_error( ctx
, "Expected `]'" );
402 /* Parse source register operand.
403 * <register_src> ::= <register_file_bracket_index> `]' |
404 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
405 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
406 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
410 struct translate_ctx
*ctx
,
420 *ind_comp
= TGSI_SWIZZLE_X
;
421 if (!parse_register_file_bracket( ctx
, file
))
423 eat_opt_white( &ctx
->cur
);
425 if (parse_file( &cur
, ind_file
)) {
426 if (!parse_register_dst( ctx
, ind_file
, ind_index
))
428 eat_opt_white( &ctx
->cur
);
430 if (*ctx
->cur
== '.') {
432 eat_opt_white(&ctx
->cur
);
434 switch (uprcase(*ctx
->cur
)) {
436 *ind_comp
= TGSI_SWIZZLE_X
;
439 *ind_comp
= TGSI_SWIZZLE_Y
;
442 *ind_comp
= TGSI_SWIZZLE_Z
;
445 *ind_comp
= TGSI_SWIZZLE_W
;
448 report_error(ctx
, "Expected indirect register swizzle component `x', `y', `z' or `w'");
452 eat_opt_white(&ctx
->cur
);
455 if (*ctx
->cur
== '+' || *ctx
->cur
== '-') {
458 negate
= *ctx
->cur
== '-';
460 eat_opt_white( &ctx
->cur
);
461 if (!parse_uint( &ctx
->cur
, &uindex
)) {
462 report_error( ctx
, "Expected literal unsigned integer" );
466 *index
= -(int) uindex
;
468 *index
= (int) uindex
;
475 if (!parse_uint( &ctx
->cur
, &uindex
)) {
476 report_error( ctx
, "Expected literal unsigned integer" );
479 *index
= (int) uindex
;
480 *ind_file
= TGSI_FILE_NULL
;
483 eat_opt_white( &ctx
->cur
);
484 if (*ctx
->cur
!= ']') {
485 report_error( ctx
, "Expected `]'" );
492 /* Parse register declaration.
493 * <register_dcl> ::= <register_file_bracket_index> `]' |
494 * <register_file_bracket_index> `..' <index> `]'
498 struct translate_ctx
*ctx
,
503 if (!parse_register_file_bracket_index( ctx
, file
, first
))
505 eat_opt_white( &ctx
->cur
);
506 if (ctx
->cur
[0] == '.' && ctx
->cur
[1] == '.') {
510 eat_opt_white( &ctx
->cur
);
511 if (!parse_uint( &ctx
->cur
, &uindex
)) {
512 report_error( ctx
, "Expected literal integer" );
515 *last
= (int) uindex
;
516 eat_opt_white( &ctx
->cur
);
521 if (*ctx
->cur
!= ']') {
522 report_error( ctx
, "Expected `]' or `..'" );
532 struct translate_ctx
*ctx
,
533 struct tgsi_full_dst_register
*dst
)
540 if (!parse_register_dst( ctx
, &file
, &index
))
544 eat_opt_white( &cur
);
546 if (!parse_opt_writemask( ctx
, &writemask
))
549 dst
->Register
.File
= file
;
550 dst
->Register
.Index
= index
;
551 dst
->Register
.WriteMask
= writemask
;
556 parse_optional_swizzle(
557 struct translate_ctx
*ctx
,
559 boolean
*parsed_swizzle
)
561 const char *cur
= ctx
->cur
;
563 *parsed_swizzle
= FALSE
;
565 eat_opt_white( &cur
);
570 eat_opt_white( &cur
);
571 for (i
= 0; i
< 4; i
++) {
572 if (uprcase( *cur
) == 'X')
573 swizzle
[i
] = TGSI_SWIZZLE_X
;
574 else if (uprcase( *cur
) == 'Y')
575 swizzle
[i
] = TGSI_SWIZZLE_Y
;
576 else if (uprcase( *cur
) == 'Z')
577 swizzle
[i
] = TGSI_SWIZZLE_Z
;
578 else if (uprcase( *cur
) == 'W')
579 swizzle
[i
] = TGSI_SWIZZLE_W
;
581 report_error( ctx
, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" );
586 *parsed_swizzle
= TRUE
;
594 struct translate_ctx
*ctx
,
595 struct tgsi_full_src_register
*src
)
603 boolean parsed_swizzle
;
605 if (*ctx
->cur
== '-') {
607 eat_opt_white( &ctx
->cur
);
608 src
->Register
.Negate
= 1;
611 if (*ctx
->cur
== '|') {
613 eat_opt_white( &ctx
->cur
);
614 src
->Register
.Absolute
= 1;
617 if (!parse_register_src(ctx
, &file
, &index
, &ind_file
, &ind_index
, &ind_comp
))
619 src
->Register
.File
= file
;
620 src
->Register
.Index
= index
;
621 if (ind_file
!= TGSI_FILE_NULL
) {
622 src
->Register
.Indirect
= 1;
623 src
->Indirect
.File
= ind_file
;
624 src
->Indirect
.Index
= ind_index
;
625 src
->Indirect
.SwizzleX
= ind_comp
;
626 src
->Indirect
.SwizzleY
= ind_comp
;
627 src
->Indirect
.SwizzleZ
= ind_comp
;
628 src
->Indirect
.SwizzleW
= ind_comp
;
631 /* Parse optional swizzle.
633 if (parse_optional_swizzle( ctx
, swizzle
, &parsed_swizzle
)) {
634 if (parsed_swizzle
) {
635 src
->Register
.SwizzleX
= swizzle
[0];
636 src
->Register
.SwizzleY
= swizzle
[1];
637 src
->Register
.SwizzleZ
= swizzle
[2];
638 src
->Register
.SwizzleW
= swizzle
[3];
642 if (src
->Register
.Absolute
) {
643 eat_opt_white( &ctx
->cur
);
644 if (*ctx
->cur
!= '|') {
645 report_error( ctx
, "Expected `|'" );
655 static const char *texture_names
[TGSI_TEXTURE_COUNT
] =
669 match_inst_mnemonic(const char **pcur
,
670 const struct tgsi_opcode_info
*info
)
672 if (str_match_no_case(pcur
, info
->mnemonic
)) {
680 struct translate_ctx
*ctx
,
684 uint saturate
= TGSI_SAT_NONE
;
685 const struct tgsi_opcode_info
*info
;
686 struct tgsi_full_instruction inst
;
689 /* Parse instruction name.
691 eat_opt_white( &ctx
->cur
);
692 for (i
= 0; i
< TGSI_OPCODE_LAST
; i
++) {
693 const char *cur
= ctx
->cur
;
695 info
= tgsi_get_opcode_info( i
);
696 if (match_inst_mnemonic(&cur
, info
)) {
697 if (str_match_no_case( &cur
, "_SATNV" ))
698 saturate
= TGSI_SAT_MINUS_PLUS_ONE
;
699 else if (str_match_no_case( &cur
, "_SAT" ))
700 saturate
= TGSI_SAT_ZERO_ONE
;
702 if (info
->num_dst
+ info
->num_src
+ info
->is_tex
== 0) {
703 if (!is_digit_alpha_underscore( cur
)) {
708 else if (*cur
== '\0' || eat_white( &cur
)) {
714 if (i
== TGSI_OPCODE_LAST
) {
716 report_error( ctx
, "Unknown opcode" );
718 report_error( ctx
, "Expected `DCL', `IMM' or a label" );
722 inst
= tgsi_default_full_instruction();
723 inst
.Instruction
.Opcode
= i
;
724 inst
.Instruction
.Saturate
= saturate
;
725 inst
.Instruction
.NumDstRegs
= info
->num_dst
;
726 inst
.Instruction
.NumSrcRegs
= info
->num_src
;
728 /* Parse instruction operands.
730 for (i
= 0; i
< info
->num_dst
+ info
->num_src
+ info
->is_tex
; i
++) {
732 eat_opt_white( &ctx
->cur
);
733 if (*ctx
->cur
!= ',') {
734 report_error( ctx
, "Expected `,'" );
738 eat_opt_white( &ctx
->cur
);
741 if (i
< info
->num_dst
) {
742 if (!parse_dst_operand( ctx
, &inst
.Dst
[i
] ))
745 else if (i
< info
->num_dst
+ info
->num_src
) {
746 if (!parse_src_operand( ctx
, &inst
.Src
[i
- info
->num_dst
] ))
752 for (j
= 0; j
< TGSI_TEXTURE_COUNT
; j
++) {
753 if (str_match_no_case( &ctx
->cur
, texture_names
[j
] )) {
754 if (!is_digit_alpha_underscore( ctx
->cur
)) {
755 inst
.Instruction
.Texture
= 1;
756 inst
.Texture
.Texture
= j
;
761 if (j
== TGSI_TEXTURE_COUNT
) {
762 report_error( ctx
, "Expected texture target" );
768 if (info
->is_branch
) {
771 eat_opt_white( &ctx
->cur
);
772 if (*ctx
->cur
!= ':') {
773 report_error( ctx
, "Expected `:'" );
777 eat_opt_white( &ctx
->cur
);
778 if (!parse_uint( &ctx
->cur
, &target
)) {
779 report_error( ctx
, "Expected a label" );
782 inst
.Instruction
.Label
= 1;
783 inst
.Label
.Label
= target
;
786 advance
= tgsi_build_full_instruction(
790 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
793 ctx
->tokens_cur
+= advance
;
798 static const char *semantic_names
[TGSI_SEMANTIC_COUNT
] =
812 static const char *interpolate_names
[TGSI_INTERPOLATE_COUNT
] =
819 static boolean
parse_declaration( struct translate_ctx
*ctx
)
821 struct tgsi_full_declaration decl
;
829 assert(Elements(semantic_names
) == TGSI_SEMANTIC_COUNT
);
830 assert(Elements(interpolate_names
) == TGSI_INTERPOLATE_COUNT
);
832 if (!eat_white( &ctx
->cur
)) {
833 report_error( ctx
, "Syntax error" );
836 if (!parse_register_dcl( ctx
, &file
, &first
, &last
))
838 if (!parse_opt_writemask( ctx
, &writemask
))
841 decl
= tgsi_default_full_declaration();
842 decl
.Declaration
.File
= file
;
843 decl
.Declaration
.UsageMask
= writemask
;
844 decl
.Range
.First
= first
;
845 decl
.Range
.Last
= last
;
848 eat_opt_white( &cur
);
853 eat_opt_white( &cur
);
854 for (i
= 0; i
< TGSI_SEMANTIC_COUNT
; i
++) {
855 if (str_match_no_case( &cur
, semantic_names
[i
] )) {
856 const char *cur2
= cur
;
859 if (is_digit_alpha_underscore( cur
))
861 eat_opt_white( &cur2
);
864 eat_opt_white( &cur2
);
865 if (!parse_uint( &cur2
, &index
)) {
866 report_error( ctx
, "Expected literal integer" );
869 eat_opt_white( &cur2
);
871 report_error( ctx
, "Expected `]'" );
876 decl
.Semantic
.Index
= index
;
881 decl
.Declaration
.Semantic
= 1;
882 decl
.Semantic
.Name
= i
;
891 eat_opt_white( &cur
);
896 eat_opt_white( &cur
);
897 for (i
= 0; i
< TGSI_INTERPOLATE_COUNT
; i
++) {
898 if (str_match_no_case( &cur
, interpolate_names
[i
] )) {
899 if (is_digit_alpha_underscore( cur
))
901 decl
.Declaration
.Interpolate
= i
;
907 if (i
== TGSI_INTERPOLATE_COUNT
) {
908 report_error( ctx
, "Expected semantic or interpolate attribute" );
913 advance
= tgsi_build_full_declaration(
917 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
920 ctx
->tokens_cur
+= advance
;
925 static boolean
parse_immediate( struct translate_ctx
*ctx
)
927 struct tgsi_full_immediate imm
;
932 if (!eat_white( &ctx
->cur
)) {
933 report_error( ctx
, "Syntax error" );
936 if (!str_match_no_case( &ctx
->cur
, "FLT32" ) || is_digit_alpha_underscore( ctx
->cur
)) {
937 report_error( ctx
, "Expected `FLT32'" );
940 eat_opt_white( &ctx
->cur
);
941 if (*ctx
->cur
!= '{') {
942 report_error( ctx
, "Expected `{'" );
946 for (i
= 0; i
< 4; i
++) {
947 eat_opt_white( &ctx
->cur
);
949 if (*ctx
->cur
!= ',') {
950 report_error( ctx
, "Expected `,'" );
954 eat_opt_white( &ctx
->cur
);
956 if (!parse_float( &ctx
->cur
, &values
[i
] )) {
957 report_error( ctx
, "Expected literal floating point" );
961 eat_opt_white( &ctx
->cur
);
962 if (*ctx
->cur
!= '}') {
963 report_error( ctx
, "Expected `}'" );
968 imm
= tgsi_default_full_immediate();
969 imm
.Immediate
.NrTokens
+= 4;
970 imm
.Immediate
.DataType
= TGSI_IMM_FLOAT32
;
971 imm
.u
[0].Float
= values
[0];
972 imm
.u
[1].Float
= values
[1];
973 imm
.u
[2].Float
= values
[2];
974 imm
.u
[3].Float
= values
[3];
976 advance
= tgsi_build_full_immediate(
980 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
983 ctx
->tokens_cur
+= advance
;
988 static const char *property_names
[] =
990 "GS_INPUT_PRIMITIVE",
991 "GS_OUTPUT_PRIMITIVE",
992 "GS_MAX_OUTPUT_VERTICES"
995 static const char *primitive_names
[] =
1010 parse_primitive( const char **pcur
, uint
*primitive
)
1014 for (i
= 0; i
< PIPE_PRIM_MAX
; i
++) {
1015 const char *cur
= *pcur
;
1017 if (str_match_no_case( &cur
, primitive_names
[i
])) {
1027 static boolean
parse_property( struct translate_ctx
*ctx
)
1029 struct tgsi_full_property prop
;
1035 if (!eat_white( &ctx
->cur
)) {
1036 report_error( ctx
, "Syntax error" );
1039 if (!parse_identifier( &ctx
->cur
, id
)) {
1040 report_error( ctx
, "Syntax error" );
1043 for (property_name
= 0; property_name
< TGSI_PROPERTY_COUNT
;
1045 if (streq_nocase_uprcase(id
, property_names
[property_name
])) {
1049 if (property_name
>= TGSI_PROPERTY_COUNT
) {
1050 debug_printf( "\nError: Unknown property : '%s'", id
);
1054 eat_opt_white( &ctx
->cur
);
1055 switch(property_name
) {
1056 case TGSI_PROPERTY_GS_INPUT_PRIM
:
1057 case TGSI_PROPERTY_GS_OUTPUT_PRIM
:
1058 if (!parse_primitive(&ctx
->cur
, &values
[0] )) {
1059 report_error( ctx
, "Unknown primitive name as property!" );
1064 if (!parse_uint(&ctx
->cur
, &values
[0] )) {
1065 report_error( ctx
, "Expected unsigned integer as property!" );
1070 prop
= tgsi_default_full_property();
1071 prop
.Property
.PropertyName
= property_name
;
1072 prop
.Property
.NrTokens
+= 1;
1073 prop
.u
[0].Data
= values
[0];
1075 advance
= tgsi_build_full_property(
1079 (uint
) (ctx
->tokens_end
- ctx
->tokens_cur
) );
1082 ctx
->tokens_cur
+= advance
;
1088 static boolean
translate( struct translate_ctx
*ctx
)
1090 eat_opt_white( &ctx
->cur
);
1091 if (!parse_header( ctx
))
1094 while (*ctx
->cur
!= '\0') {
1096 if (!eat_white( &ctx
->cur
)) {
1097 report_error( ctx
, "Syntax error" );
1101 if (*ctx
->cur
== '\0')
1103 if (parse_label( ctx
, &label_val
)) {
1104 if (!parse_instruction( ctx
, TRUE
))
1107 else if (str_match_no_case( &ctx
->cur
, "DCL" )) {
1108 if (!parse_declaration( ctx
))
1111 else if (str_match_no_case( &ctx
->cur
, "IMM" )) {
1112 if (!parse_immediate( ctx
))
1115 else if (str_match_no_case( &ctx
->cur
, "PROPERTY" )) {
1116 if (!parse_property( ctx
))
1119 else if (!parse_instruction( ctx
, FALSE
)) {
1128 tgsi_text_translate(
1130 struct tgsi_token
*tokens
,
1133 struct translate_ctx ctx
;
1137 ctx
.tokens
= tokens
;
1138 ctx
.tokens_cur
= tokens
;
1139 ctx
.tokens_end
= tokens
+ num_tokens
;
1141 if (!translate( &ctx
))
1144 return tgsi_sanity_check( tokens
);