egl: Implement _eglFiniDisplay.
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_text.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28 #include "util/u_debug.h"
29 #include "util/u_memory.h"
30 #include "tgsi_text.h"
31 #include "tgsi_build.h"
32 #include "tgsi_info.h"
33 #include "tgsi_parse.h"
34 #include "tgsi_sanity.h"
35 #include "tgsi_util.h"
36
37 static boolean is_alpha_underscore( const char *cur )
38 {
39 return
40 (*cur >= 'a' && *cur <= 'z') ||
41 (*cur >= 'A' && *cur <= 'Z') ||
42 *cur == '_';
43 }
44
45 static boolean is_digit( const char *cur )
46 {
47 return *cur >= '0' && *cur <= '9';
48 }
49
50 static boolean is_digit_alpha_underscore( const char *cur )
51 {
52 return is_digit( cur ) || is_alpha_underscore( cur );
53 }
54
55 static boolean uprcase( char c )
56 {
57 if (c >= 'a' && c <= 'z')
58 return c += 'A' - 'a';
59 return c;
60 }
61
62 static boolean str_match_no_case( const char **pcur, const char *str )
63 {
64 const char *cur = *pcur;
65
66 while (*str != '\0' && *str == uprcase( *cur )) {
67 str++;
68 cur++;
69 }
70 if (*str == '\0') {
71 *pcur = cur;
72 return TRUE;
73 }
74 return FALSE;
75 }
76
77 /* Eat zero or more whitespaces.
78 */
79 static void eat_opt_white( const char **pcur )
80 {
81 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
82 (*pcur)++;
83 }
84
85 /* Eat one or more whitespaces.
86 * Return TRUE if at least one whitespace eaten.
87 */
88 static boolean eat_white( const char **pcur )
89 {
90 const char *cur = *pcur;
91
92 eat_opt_white( pcur );
93 return *pcur > cur;
94 }
95
96 /* Parse unsigned integer.
97 * No checks for overflow.
98 */
99 static boolean parse_uint( const char **pcur, uint *val )
100 {
101 const char *cur = *pcur;
102
103 if (is_digit( cur )) {
104 *val = *cur++ - '0';
105 while (is_digit( cur ))
106 *val = *val * 10 + *cur++ - '0';
107 *pcur = cur;
108 return TRUE;
109 }
110 return FALSE;
111 }
112
113 /* Parse floating point.
114 */
115 static boolean parse_float( const char **pcur, float *val )
116 {
117 const char *cur = *pcur;
118 boolean integral_part = FALSE;
119 boolean fractional_part = FALSE;
120
121 *val = (float) atof( cur );
122
123 if (*cur == '-' || *cur == '+')
124 cur++;
125 if (is_digit( cur )) {
126 cur++;
127 integral_part = TRUE;
128 while (is_digit( cur ))
129 cur++;
130 }
131 if (*cur == '.') {
132 cur++;
133 if (is_digit( cur )) {
134 cur++;
135 fractional_part = TRUE;
136 while (is_digit( cur ))
137 cur++;
138 }
139 }
140 if (!integral_part && !fractional_part)
141 return FALSE;
142 if (uprcase( *cur ) == 'E') {
143 cur++;
144 if (*cur == '-' || *cur == '+')
145 cur++;
146 if (is_digit( cur )) {
147 cur++;
148 while (is_digit( cur ))
149 cur++;
150 }
151 else
152 return FALSE;
153 }
154 *pcur = cur;
155 return TRUE;
156 }
157
158 struct translate_ctx
159 {
160 const char *text;
161 const char *cur;
162 struct tgsi_token *tokens;
163 struct tgsi_token *tokens_cur;
164 struct tgsi_token *tokens_end;
165 struct tgsi_header *header;
166 };
167
168 static void report_error( struct translate_ctx *ctx, const char *msg )
169 {
170 debug_printf( "\nError: %s", msg );
171 }
172
173 /* Parse shader header.
174 * Return TRUE for one of the following headers.
175 * FRAG1.1
176 * GEOM1.1
177 * VERT1.1
178 */
179 static boolean parse_header( struct translate_ctx *ctx )
180 {
181 uint processor;
182
183 if (str_match_no_case( &ctx->cur, "FRAG1.1" ))
184 processor = TGSI_PROCESSOR_FRAGMENT;
185 else if (str_match_no_case( &ctx->cur, "VERT1.1" ))
186 processor = TGSI_PROCESSOR_VERTEX;
187 else if (str_match_no_case( &ctx->cur, "GEOM1.1" ))
188 processor = TGSI_PROCESSOR_GEOMETRY;
189 else {
190 report_error( ctx, "Unknown header" );
191 return FALSE;
192 }
193
194 if (ctx->tokens_cur >= ctx->tokens_end)
195 return FALSE;
196 *(struct tgsi_version *) ctx->tokens_cur++ = tgsi_build_version();
197
198 if (ctx->tokens_cur >= ctx->tokens_end)
199 return FALSE;
200 ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
201 *ctx->header = tgsi_build_header();
202
203 if (ctx->tokens_cur >= ctx->tokens_end)
204 return FALSE;
205 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
206
207 return TRUE;
208 }
209
210 static boolean parse_label( struct translate_ctx *ctx, uint *val )
211 {
212 const char *cur = ctx->cur;
213
214 if (parse_uint( &cur, val )) {
215 eat_opt_white( &cur );
216 if (*cur == ':') {
217 cur++;
218 ctx->cur = cur;
219 return TRUE;
220 }
221 }
222 return FALSE;
223 }
224
225 static const char *file_names[TGSI_FILE_COUNT] =
226 {
227 "NULL",
228 "CONST",
229 "IN",
230 "OUT",
231 "TEMP",
232 "SAMP",
233 "ADDR",
234 "IMM",
235 "LOOP"
236 };
237
238 static boolean
239 parse_file( const char **pcur, uint *file )
240 {
241 uint i;
242
243 for (i = 0; i < TGSI_FILE_COUNT; i++) {
244 const char *cur = *pcur;
245
246 if (str_match_no_case( &cur, file_names[i] )) {
247 if (!is_digit_alpha_underscore( cur )) {
248 *pcur = cur;
249 *file = i;
250 return TRUE;
251 }
252 }
253 }
254 return FALSE;
255 }
256
257 static boolean
258 parse_opt_writemask(
259 struct translate_ctx *ctx,
260 uint *writemask )
261 {
262 const char *cur;
263
264 cur = ctx->cur;
265 eat_opt_white( &cur );
266 if (*cur == '.') {
267 cur++;
268 *writemask = TGSI_WRITEMASK_NONE;
269 eat_opt_white( &cur );
270 if (uprcase( *cur ) == 'X') {
271 cur++;
272 *writemask |= TGSI_WRITEMASK_X;
273 }
274 if (uprcase( *cur ) == 'Y') {
275 cur++;
276 *writemask |= TGSI_WRITEMASK_Y;
277 }
278 if (uprcase( *cur ) == 'Z') {
279 cur++;
280 *writemask |= TGSI_WRITEMASK_Z;
281 }
282 if (uprcase( *cur ) == 'W') {
283 cur++;
284 *writemask |= TGSI_WRITEMASK_W;
285 }
286
287 if (*writemask == TGSI_WRITEMASK_NONE) {
288 report_error( ctx, "Writemask expected" );
289 return FALSE;
290 }
291
292 ctx->cur = cur;
293 }
294 else {
295 *writemask = TGSI_WRITEMASK_XYZW;
296 }
297 return TRUE;
298 }
299
300 /* <register_file_bracket> ::= <file> `['
301 */
302 static boolean
303 parse_register_file_bracket(
304 struct translate_ctx *ctx,
305 uint *file )
306 {
307 if (!parse_file( &ctx->cur, file )) {
308 report_error( ctx, "Unknown register file" );
309 return FALSE;
310 }
311 eat_opt_white( &ctx->cur );
312 if (*ctx->cur != '[') {
313 report_error( ctx, "Expected `['" );
314 return FALSE;
315 }
316 ctx->cur++;
317 return TRUE;
318 }
319
320 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
321 */
322 static boolean
323 parse_register_file_bracket_index(
324 struct translate_ctx *ctx,
325 uint *file,
326 int *index )
327 {
328 uint uindex;
329
330 if (!parse_register_file_bracket( ctx, file ))
331 return FALSE;
332 eat_opt_white( &ctx->cur );
333 if (!parse_uint( &ctx->cur, &uindex )) {
334 report_error( ctx, "Expected literal unsigned integer" );
335 return FALSE;
336 }
337 *index = (int) uindex;
338 return TRUE;
339 }
340
341 /* Parse destination register operand.
342 * <register_dst> ::= <register_file_bracket_index> `]'
343 */
344 static boolean
345 parse_register_dst(
346 struct translate_ctx *ctx,
347 uint *file,
348 int *index )
349 {
350 if (!parse_register_file_bracket_index( ctx, file, index ))
351 return FALSE;
352 eat_opt_white( &ctx->cur );
353 if (*ctx->cur != ']') {
354 report_error( ctx, "Expected `]'" );
355 return FALSE;
356 }
357 ctx->cur++;
358 return TRUE;
359 }
360
361 /* Parse source register operand.
362 * <register_src> ::= <register_file_bracket_index> `]' |
363 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
364 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
365 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
366 */
367 static boolean
368 parse_register_src(
369 struct translate_ctx *ctx,
370 uint *file,
371 int *index,
372 uint *ind_file,
373 int *ind_index,
374 uint *ind_comp)
375 {
376 const char *cur;
377 uint uindex;
378
379 *ind_comp = TGSI_SWIZZLE_X;
380 if (!parse_register_file_bracket( ctx, file ))
381 return FALSE;
382 eat_opt_white( &ctx->cur );
383 cur = ctx->cur;
384 if (parse_file( &cur, ind_file )) {
385 if (!parse_register_dst( ctx, ind_file, ind_index ))
386 return FALSE;
387 eat_opt_white( &ctx->cur );
388
389 if (*ctx->cur == '.') {
390 ctx->cur++;
391 eat_opt_white(&ctx->cur);
392
393 switch (uprcase(*ctx->cur)) {
394 case 'X':
395 *ind_comp = TGSI_SWIZZLE_X;
396 break;
397 case 'Y':
398 *ind_comp = TGSI_SWIZZLE_Y;
399 break;
400 case 'Z':
401 *ind_comp = TGSI_SWIZZLE_Z;
402 break;
403 case 'W':
404 *ind_comp = TGSI_SWIZZLE_W;
405 break;
406 default:
407 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
408 return FALSE;
409 }
410 ctx->cur++;
411 eat_opt_white(&ctx->cur);
412 }
413
414 if (*ctx->cur == '+' || *ctx->cur == '-') {
415 boolean negate;
416
417 negate = *ctx->cur == '-';
418 ctx->cur++;
419 eat_opt_white( &ctx->cur );
420 if (!parse_uint( &ctx->cur, &uindex )) {
421 report_error( ctx, "Expected literal unsigned integer" );
422 return FALSE;
423 }
424 if (negate)
425 *index = -(int) uindex;
426 else
427 *index = (int) uindex;
428 }
429 else {
430 *index = 0;
431 }
432 }
433 else {
434 if (!parse_uint( &ctx->cur, &uindex )) {
435 report_error( ctx, "Expected literal unsigned integer" );
436 return FALSE;
437 }
438 *index = (int) uindex;
439 *ind_file = TGSI_FILE_NULL;
440 *ind_index = 0;
441 }
442 eat_opt_white( &ctx->cur );
443 if (*ctx->cur != ']') {
444 report_error( ctx, "Expected `]'" );
445 return FALSE;
446 }
447 ctx->cur++;
448 return TRUE;
449 }
450
451 /* Parse register declaration.
452 * <register_dcl> ::= <register_file_bracket_index> `]' |
453 * <register_file_bracket_index> `..' <index> `]'
454 */
455 static boolean
456 parse_register_dcl(
457 struct translate_ctx *ctx,
458 uint *file,
459 int *first,
460 int *last )
461 {
462 if (!parse_register_file_bracket_index( ctx, file, first ))
463 return FALSE;
464 eat_opt_white( &ctx->cur );
465 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
466 uint uindex;
467
468 ctx->cur += 2;
469 eat_opt_white( &ctx->cur );
470 if (!parse_uint( &ctx->cur, &uindex )) {
471 report_error( ctx, "Expected literal integer" );
472 return FALSE;
473 }
474 *last = (int) uindex;
475 eat_opt_white( &ctx->cur );
476 }
477 else {
478 *last = *first;
479 }
480 if (*ctx->cur != ']') {
481 report_error( ctx, "Expected `]' or `..'" );
482 return FALSE;
483 }
484 ctx->cur++;
485 return TRUE;
486 }
487
488 static const char *modulate_names[TGSI_MODULATE_COUNT] =
489 {
490 "_1X",
491 "_2X",
492 "_4X",
493 "_8X",
494 "_D2",
495 "_D4",
496 "_D8"
497 };
498
499 static boolean
500 parse_dst_operand(
501 struct translate_ctx *ctx,
502 struct tgsi_full_dst_register *dst )
503 {
504 uint file;
505 int index;
506 uint writemask;
507 const char *cur;
508
509 if (!parse_register_dst( ctx, &file, &index ))
510 return FALSE;
511
512 cur = ctx->cur;
513 eat_opt_white( &cur );
514 if (*cur == '_') {
515 uint i;
516
517 for (i = 0; i < TGSI_MODULATE_COUNT; i++) {
518 if (str_match_no_case( &cur, modulate_names[i] )) {
519 if (!is_digit_alpha_underscore( cur )) {
520 dst->DstRegisterExtModulate.Modulate = i;
521 ctx->cur = cur;
522 break;
523 }
524 }
525 }
526 }
527
528 if (!parse_opt_writemask( ctx, &writemask ))
529 return FALSE;
530
531 dst->DstRegister.File = file;
532 dst->DstRegister.Index = index;
533 dst->DstRegister.WriteMask = writemask;
534 return TRUE;
535 }
536
537 static boolean
538 parse_optional_swizzle(
539 struct translate_ctx *ctx,
540 uint swizzle[4],
541 boolean *parsed_swizzle,
542 boolean *parsed_extswizzle )
543 {
544 const char *cur = ctx->cur;
545
546 *parsed_swizzle = FALSE;
547 *parsed_extswizzle = FALSE;
548
549 eat_opt_white( &cur );
550 if (*cur == '.') {
551 uint i;
552
553 cur++;
554 eat_opt_white( &cur );
555 for (i = 0; i < 4; i++) {
556 if (uprcase( *cur ) == 'X')
557 swizzle[i] = TGSI_SWIZZLE_X;
558 else if (uprcase( *cur ) == 'Y')
559 swizzle[i] = TGSI_SWIZZLE_Y;
560 else if (uprcase( *cur ) == 'Z')
561 swizzle[i] = TGSI_SWIZZLE_Z;
562 else if (uprcase( *cur ) == 'W')
563 swizzle[i] = TGSI_SWIZZLE_W;
564 else {
565 if (*cur == '0')
566 swizzle[i] = TGSI_EXTSWIZZLE_ZERO;
567 else if (*cur == '1')
568 swizzle[i] = TGSI_EXTSWIZZLE_ONE;
569 else {
570 report_error( ctx, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" );
571 return FALSE;
572 }
573 *parsed_extswizzle = TRUE;
574 }
575 cur++;
576 }
577 *parsed_swizzle = TRUE;
578 ctx->cur = cur;
579 }
580 return TRUE;
581 }
582
583 static boolean
584 parse_src_operand(
585 struct translate_ctx *ctx,
586 struct tgsi_full_src_register *src )
587 {
588 const char *cur;
589 float value;
590 uint file;
591 int index;
592 uint ind_file;
593 int ind_index;
594 uint ind_comp;
595 uint swizzle[4];
596 boolean parsed_ext_negate_paren = FALSE;
597 boolean parsed_swizzle;
598 boolean parsed_extswizzle;
599
600 if (*ctx->cur == '-') {
601 cur = ctx->cur;
602 cur++;
603 eat_opt_white( &cur );
604 if (*cur == '(') {
605 cur++;
606 src->SrcRegisterExtMod.Negate = 1;
607 eat_opt_white( &cur );
608 ctx->cur = cur;
609 parsed_ext_negate_paren = TRUE;
610 }
611 else if (*cur == '|') {
612 cur++;
613 src->SrcRegisterExtMod.Negate = 1;
614 src->SrcRegisterExtMod.Absolute = 1;
615 eat_opt_white(&cur);
616 ctx->cur = cur;
617 }
618 }
619 else if (*ctx->cur == '|') {
620 ctx->cur++;
621 eat_opt_white( &ctx->cur );
622 src->SrcRegisterExtMod.Absolute = 1;
623 }
624
625 if (*ctx->cur == '-') {
626 ctx->cur++;
627 eat_opt_white( &ctx->cur );
628 src->SrcRegister.Negate = 1;
629 }
630
631 cur = ctx->cur;
632 if (parse_float( &cur, &value )) {
633 if (value == 2.0f) {
634 eat_opt_white( &cur );
635 if (*cur != '*') {
636 report_error( ctx, "Expected `*'" );
637 return FALSE;
638 }
639 cur++;
640 if (*cur != '(') {
641 report_error( ctx, "Expected `('" );
642 return FALSE;
643 }
644 cur++;
645 src->SrcRegisterExtMod.Scale2X = 1;
646 eat_opt_white( &cur );
647 ctx->cur = cur;
648 }
649 }
650
651 if (*ctx->cur == '(') {
652 ctx->cur++;
653 eat_opt_white( &ctx->cur );
654 src->SrcRegisterExtMod.Bias = 1;
655 }
656
657 cur = ctx->cur;
658 if (parse_float( &cur, &value )) {
659 if (value == 1.0f) {
660 eat_opt_white( &cur );
661 if (*cur != '-') {
662 report_error( ctx, "Expected `-'" );
663 return FALSE;
664 }
665 cur++;
666 if (*cur != '(') {
667 report_error( ctx, "Expected `('" );
668 return FALSE;
669 }
670 cur++;
671 src->SrcRegisterExtMod.Complement = 1;
672 eat_opt_white( &cur );
673 ctx->cur = cur;
674 }
675 }
676
677 if (!parse_register_src(ctx, &file, &index, &ind_file, &ind_index, &ind_comp))
678 return FALSE;
679 src->SrcRegister.File = file;
680 src->SrcRegister.Index = index;
681 if (ind_file != TGSI_FILE_NULL) {
682 src->SrcRegister.Indirect = 1;
683 src->SrcRegisterInd.File = ind_file;
684 src->SrcRegisterInd.Index = ind_index;
685 src->SrcRegisterInd.SwizzleX = ind_comp;
686 src->SrcRegisterInd.SwizzleY = ind_comp;
687 src->SrcRegisterInd.SwizzleZ = ind_comp;
688 src->SrcRegisterInd.SwizzleW = ind_comp;
689 }
690
691 /* Parse optional swizzle.
692 */
693 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, &parsed_extswizzle )) {
694 if (parsed_extswizzle) {
695 assert( parsed_swizzle );
696
697 src->SrcRegisterExtSwz.ExtSwizzleX = swizzle[0];
698 src->SrcRegisterExtSwz.ExtSwizzleY = swizzle[1];
699 src->SrcRegisterExtSwz.ExtSwizzleZ = swizzle[2];
700 src->SrcRegisterExtSwz.ExtSwizzleW = swizzle[3];
701 }
702 else if (parsed_swizzle) {
703 src->SrcRegister.SwizzleX = swizzle[0];
704 src->SrcRegister.SwizzleY = swizzle[1];
705 src->SrcRegister.SwizzleZ = swizzle[2];
706 src->SrcRegister.SwizzleW = swizzle[3];
707 }
708 }
709
710 if (src->SrcRegisterExtMod.Complement) {
711 eat_opt_white( &ctx->cur );
712 if (*ctx->cur != ')') {
713 report_error( ctx, "Expected `)'" );
714 return FALSE;
715 }
716 ctx->cur++;
717 }
718
719 if (src->SrcRegisterExtMod.Bias) {
720 eat_opt_white( &ctx->cur );
721 if (*ctx->cur != ')') {
722 report_error( ctx, "Expected `)'" );
723 return FALSE;
724 }
725 ctx->cur++;
726 eat_opt_white( &ctx->cur );
727 if (*ctx->cur != '-') {
728 report_error( ctx, "Expected `-'" );
729 return FALSE;
730 }
731 ctx->cur++;
732 eat_opt_white( &ctx->cur );
733 if (!parse_float( &ctx->cur, &value )) {
734 report_error( ctx, "Expected literal floating point" );
735 return FALSE;
736 }
737 if (value != 0.5f) {
738 report_error( ctx, "Expected 0.5" );
739 return FALSE;
740 }
741 }
742
743 if (src->SrcRegisterExtMod.Scale2X) {
744 eat_opt_white( &ctx->cur );
745 if (*ctx->cur != ')') {
746 report_error( ctx, "Expected `)'" );
747 return FALSE;
748 }
749 ctx->cur++;
750 }
751
752 if (src->SrcRegisterExtMod.Absolute) {
753 eat_opt_white( &ctx->cur );
754 if (*ctx->cur != '|') {
755 report_error( ctx, "Expected `|'" );
756 return FALSE;
757 }
758 ctx->cur++;
759 }
760
761 if (parsed_ext_negate_paren) {
762 eat_opt_white( &ctx->cur );
763 if (*ctx->cur != ')') {
764 report_error( ctx, "Expected `)'" );
765 return FALSE;
766 }
767 ctx->cur++;
768 }
769
770 return TRUE;
771 }
772
773 static const char *texture_names[TGSI_TEXTURE_COUNT] =
774 {
775 "UNKNOWN",
776 "1D",
777 "2D",
778 "3D",
779 "CUBE",
780 "RECT",
781 "SHADOW1D",
782 "SHADOW2D",
783 "SHADOWRECT"
784 };
785
786 static boolean
787 match_inst_mnemonic(const char **pcur,
788 const struct tgsi_opcode_info *info)
789 {
790 if (str_match_no_case(pcur, info->mnemonic)) {
791 return TRUE;
792 }
793 return FALSE;
794 }
795
796 static boolean
797 parse_instruction(
798 struct translate_ctx *ctx,
799 boolean has_label )
800 {
801 uint i;
802 uint saturate = TGSI_SAT_NONE;
803 const struct tgsi_opcode_info *info;
804 struct tgsi_full_instruction inst;
805 uint advance;
806
807 /* Parse instruction name.
808 */
809 eat_opt_white( &ctx->cur );
810 for (i = 0; i < TGSI_OPCODE_LAST; i++) {
811 const char *cur = ctx->cur;
812
813 info = tgsi_get_opcode_info( i );
814 if (match_inst_mnemonic(&cur, info)) {
815 if (str_match_no_case( &cur, "_SATNV" ))
816 saturate = TGSI_SAT_MINUS_PLUS_ONE;
817 else if (str_match_no_case( &cur, "_SAT" ))
818 saturate = TGSI_SAT_ZERO_ONE;
819
820 if (info->num_dst + info->num_src + info->is_tex == 0) {
821 if (!is_digit_alpha_underscore( cur )) {
822 ctx->cur = cur;
823 break;
824 }
825 }
826 else if (*cur == '\0' || eat_white( &cur )) {
827 ctx->cur = cur;
828 break;
829 }
830 }
831 }
832 if (i == TGSI_OPCODE_LAST) {
833 if (has_label)
834 report_error( ctx, "Unknown opcode" );
835 else
836 report_error( ctx, "Expected `DCL', `IMM' or a label" );
837 return FALSE;
838 }
839
840 inst = tgsi_default_full_instruction();
841 inst.Instruction.Opcode = i;
842 inst.Instruction.Saturate = saturate;
843 inst.Instruction.NumDstRegs = info->num_dst;
844 inst.Instruction.NumSrcRegs = info->num_src;
845
846 /* Parse instruction operands.
847 */
848 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
849 if (i > 0) {
850 eat_opt_white( &ctx->cur );
851 if (*ctx->cur != ',') {
852 report_error( ctx, "Expected `,'" );
853 return FALSE;
854 }
855 ctx->cur++;
856 eat_opt_white( &ctx->cur );
857 }
858
859 if (i < info->num_dst) {
860 if (!parse_dst_operand( ctx, &inst.FullDstRegisters[i] ))
861 return FALSE;
862 }
863 else if (i < info->num_dst + info->num_src) {
864 if (!parse_src_operand( ctx, &inst.FullSrcRegisters[i - info->num_dst] ))
865 return FALSE;
866 }
867 else {
868 uint j;
869
870 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
871 if (str_match_no_case( &ctx->cur, texture_names[j] )) {
872 if (!is_digit_alpha_underscore( ctx->cur )) {
873 inst.InstructionExtTexture.Texture = j;
874 break;
875 }
876 }
877 }
878 if (j == TGSI_TEXTURE_COUNT) {
879 report_error( ctx, "Expected texture target" );
880 return FALSE;
881 }
882 }
883 }
884
885 if (info->is_branch) {
886 uint target;
887
888 eat_opt_white( &ctx->cur );
889 if (*ctx->cur != ':') {
890 report_error( ctx, "Expected `:'" );
891 return FALSE;
892 }
893 ctx->cur++;
894 eat_opt_white( &ctx->cur );
895 if (!parse_uint( &ctx->cur, &target )) {
896 report_error( ctx, "Expected a label" );
897 return FALSE;
898 }
899 inst.InstructionExtLabel.Label = target;
900 }
901
902 advance = tgsi_build_full_instruction(
903 &inst,
904 ctx->tokens_cur,
905 ctx->header,
906 (uint) (ctx->tokens_end - ctx->tokens_cur) );
907 if (advance == 0)
908 return FALSE;
909 ctx->tokens_cur += advance;
910
911 return TRUE;
912 }
913
914 static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
915 {
916 "POSITION",
917 "COLOR",
918 "BCOLOR",
919 "FOG",
920 "PSIZE",
921 "GENERIC",
922 "NORMAL",
923 "FACE"
924 };
925
926 static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
927 {
928 "CONSTANT",
929 "LINEAR",
930 "PERSPECTIVE"
931 };
932
933 static boolean parse_declaration( struct translate_ctx *ctx )
934 {
935 struct tgsi_full_declaration decl;
936 uint file;
937 int first;
938 int last;
939 uint writemask;
940 const char *cur;
941 uint advance;
942
943 assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT);
944 assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT);
945
946 if (!eat_white( &ctx->cur )) {
947 report_error( ctx, "Syntax error" );
948 return FALSE;
949 }
950 if (!parse_register_dcl( ctx, &file, &first, &last ))
951 return FALSE;
952 if (!parse_opt_writemask( ctx, &writemask ))
953 return FALSE;
954
955 decl = tgsi_default_full_declaration();
956 decl.Declaration.File = file;
957 decl.Declaration.UsageMask = writemask;
958 decl.DeclarationRange.First = first;
959 decl.DeclarationRange.Last = last;
960
961 cur = ctx->cur;
962 eat_opt_white( &cur );
963 if (*cur == ',') {
964 uint i;
965
966 cur++;
967 eat_opt_white( &cur );
968 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
969 if (str_match_no_case( &cur, semantic_names[i] )) {
970 const char *cur2 = cur;
971 uint index;
972
973 if (is_digit_alpha_underscore( cur ))
974 continue;
975 eat_opt_white( &cur2 );
976 if (*cur2 == '[') {
977 cur2++;
978 eat_opt_white( &cur2 );
979 if (!parse_uint( &cur2, &index )) {
980 report_error( ctx, "Expected literal integer" );
981 return FALSE;
982 }
983 eat_opt_white( &cur2 );
984 if (*cur2 != ']') {
985 report_error( ctx, "Expected `]'" );
986 return FALSE;
987 }
988 cur2++;
989
990 decl.Semantic.SemanticIndex = index;
991
992 cur = cur2;
993 }
994
995 decl.Declaration.Semantic = 1;
996 decl.Semantic.SemanticName = i;
997
998 ctx->cur = cur;
999 break;
1000 }
1001 }
1002 }
1003
1004 cur = ctx->cur;
1005 eat_opt_white( &cur );
1006 if (*cur == ',') {
1007 uint i;
1008
1009 cur++;
1010 eat_opt_white( &cur );
1011 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1012 if (str_match_no_case( &cur, interpolate_names[i] )) {
1013 if (is_digit_alpha_underscore( cur ))
1014 continue;
1015 decl.Declaration.Interpolate = i;
1016
1017 ctx->cur = cur;
1018 break;
1019 }
1020 }
1021 if (i == TGSI_INTERPOLATE_COUNT) {
1022 report_error( ctx, "Expected semantic or interpolate attribute" );
1023 return FALSE;
1024 }
1025 }
1026
1027 advance = tgsi_build_full_declaration(
1028 &decl,
1029 ctx->tokens_cur,
1030 ctx->header,
1031 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1032 if (advance == 0)
1033 return FALSE;
1034 ctx->tokens_cur += advance;
1035
1036 return TRUE;
1037 }
1038
1039 static boolean parse_immediate( struct translate_ctx *ctx )
1040 {
1041 struct tgsi_full_immediate imm;
1042 uint i;
1043 float values[4];
1044 uint advance;
1045
1046 if (!eat_white( &ctx->cur )) {
1047 report_error( ctx, "Syntax error" );
1048 return FALSE;
1049 }
1050 if (!str_match_no_case( &ctx->cur, "FLT32" ) || is_digit_alpha_underscore( ctx->cur )) {
1051 report_error( ctx, "Expected `FLT32'" );
1052 return FALSE;
1053 }
1054 eat_opt_white( &ctx->cur );
1055 if (*ctx->cur != '{') {
1056 report_error( ctx, "Expected `{'" );
1057 return FALSE;
1058 }
1059 ctx->cur++;
1060 for (i = 0; i < 4; i++) {
1061 eat_opt_white( &ctx->cur );
1062 if (i > 0) {
1063 if (*ctx->cur != ',') {
1064 report_error( ctx, "Expected `,'" );
1065 return FALSE;
1066 }
1067 ctx->cur++;
1068 eat_opt_white( &ctx->cur );
1069 }
1070 if (!parse_float( &ctx->cur, &values[i] )) {
1071 report_error( ctx, "Expected literal floating point" );
1072 return FALSE;
1073 }
1074 }
1075 eat_opt_white( &ctx->cur );
1076 if (*ctx->cur != '}') {
1077 report_error( ctx, "Expected `}'" );
1078 return FALSE;
1079 }
1080 ctx->cur++;
1081
1082 imm = tgsi_default_full_immediate();
1083 imm.Immediate.NrTokens += 4;
1084 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
1085 imm.u[0].Float = values[0];
1086 imm.u[1].Float = values[1];
1087 imm.u[2].Float = values[2];
1088 imm.u[3].Float = values[3];
1089
1090 advance = tgsi_build_full_immediate(
1091 &imm,
1092 ctx->tokens_cur,
1093 ctx->header,
1094 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1095 if (advance == 0)
1096 return FALSE;
1097 ctx->tokens_cur += advance;
1098
1099 return TRUE;
1100 }
1101
1102 static boolean translate( struct translate_ctx *ctx )
1103 {
1104 eat_opt_white( &ctx->cur );
1105 if (!parse_header( ctx ))
1106 return FALSE;
1107
1108 while (*ctx->cur != '\0') {
1109 uint label_val = 0;
1110
1111 if (!eat_white( &ctx->cur )) {
1112 report_error( ctx, "Syntax error" );
1113 return FALSE;
1114 }
1115
1116 if (*ctx->cur == '\0')
1117 break;
1118
1119 if (parse_label( ctx, &label_val )) {
1120 if (!parse_instruction( ctx, TRUE ))
1121 return FALSE;
1122 }
1123 else if (str_match_no_case( &ctx->cur, "DCL" )) {
1124 if (!parse_declaration( ctx ))
1125 return FALSE;
1126 }
1127 else if (str_match_no_case( &ctx->cur, "IMM" )) {
1128 if (!parse_immediate( ctx ))
1129 return FALSE;
1130 }
1131 else if (!parse_instruction( ctx, FALSE )) {
1132 return FALSE;
1133 }
1134 }
1135
1136 return TRUE;
1137 }
1138
1139 boolean
1140 tgsi_text_translate(
1141 const char *text,
1142 struct tgsi_token *tokens,
1143 uint num_tokens )
1144 {
1145 struct translate_ctx ctx;
1146
1147 ctx.text = text;
1148 ctx.cur = text;
1149 ctx.tokens = tokens;
1150 ctx.tokens_cur = tokens;
1151 ctx.tokens_end = tokens + num_tokens;
1152
1153 if (!translate( &ctx ))
1154 return FALSE;
1155
1156 return tgsi_sanity_check( tokens );
1157 }