Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5563 serge 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 "util/u_prim.h"
31
#include "pipe/p_defines.h"
32
#include "util/u_inlines.h"
33
#include "tgsi_text.h"
34
#include "tgsi_build.h"
35
#include "tgsi_info.h"
36
#include "tgsi_parse.h"
37
#include "tgsi_sanity.h"
38
#include "tgsi_strings.h"
39
#include "tgsi_util.h"
40
#include "tgsi_dump.h"
41
 
42
static boolean is_alpha_underscore( const char *cur )
43
{
44
   return
45
      (*cur >= 'a' && *cur <= 'z') ||
46
      (*cur >= 'A' && *cur <= 'Z') ||
47
      *cur == '_';
48
}
49
 
50
static boolean is_digit( const char *cur )
51
{
52
   return *cur >= '0' && *cur <= '9';
53
}
54
 
55
static boolean is_digit_alpha_underscore( const char *cur )
56
{
57
   return is_digit( cur ) || is_alpha_underscore( cur );
58
}
59
 
60
static char uprcase( char c )
61
{
62
   if (c >= 'a' && c <= 'z')
63
      return c + 'A' - 'a';
64
   return c;
65
}
66
 
67
/*
68
 * Ignore case of str1 and assume str1 is already uppercase.
69
 * Return TRUE iff str1 and str2 are equal.
70
 */
71
static int
72
streq_nocase_uprcase(const char *str1,
73
                     const char *str2)
74
{
75
   while (*str1 && *str2) {
76
      if (*str1 != uprcase(*str2))
77
         return FALSE;
78
      str1++;
79
      str2++;
80
   }
81
   return *str1 == 0 && *str2 == 0;
82
}
83
 
84
/* Return TRUE if both strings match.
85
 * The second string is terminated by zero.
86
 * The pointer to the first string is moved at end of the read word
87
 * on success.
88
 */
89
static boolean str_match_no_case( const char **pcur, const char *str )
90
{
91
   const char *cur = *pcur;
92
 
93
   while (*str != '\0' && *str == uprcase( *cur )) {
94
      str++;
95
      cur++;
96
   }
97
   if (*str == '\0') {
98
      *pcur = cur;
99
      return TRUE;
100
   }
101
   return FALSE;
102
}
103
 
104
/* Return TRUE if both strings match.
105
 * The first string is be terminated by a non-digit non-letter non-underscore
106
 * character, the second string is terminated by zero.
107
 * The pointer to the first string is moved at end of the read word
108
 * on success.
109
 */
110
static boolean str_match_nocase_whole( const char **pcur, const char *str )
111
{
112
   const char *cur = *pcur;
113
 
114
   if (str_match_no_case(&cur, str) &&
115
       !is_digit_alpha_underscore(cur)) {
116
      *pcur = cur;
117
      return TRUE;
118
   }
119
   return FALSE;
120
}
121
 
122
/* Eat zero or more whitespaces.
123
 */
124
static void eat_opt_white( const char **pcur )
125
{
126
   while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
127
      (*pcur)++;
128
}
129
 
130
/* Eat one or more whitespaces.
131
 * Return TRUE if at least one whitespace eaten.
132
 */
133
static boolean eat_white( const char **pcur )
134
{
135
   const char *cur = *pcur;
136
 
137
   eat_opt_white( pcur );
138
   return *pcur > cur;
139
}
140
 
141
/* Parse unsigned integer.
142
 * No checks for overflow.
143
 */
144
static boolean parse_uint( const char **pcur, uint *val )
145
{
146
   const char *cur = *pcur;
147
 
148
   if (is_digit( cur )) {
149
      *val = *cur++ - '0';
150
      while (is_digit( cur ))
151
         *val = *val * 10 + *cur++ - '0';
152
      *pcur = cur;
153
      return TRUE;
154
   }
155
   return FALSE;
156
}
157
 
158
static boolean parse_int( const char **pcur, int *val )
159
{
160
   const char *cur = *pcur;
161
   int sign = (*cur == '-' ? -1 : 1);
162
 
163
   if (*cur == '+' || *cur == '-')
164
      cur++;
165
 
166
   if (parse_uint(&cur, (uint *)val)) {
167
      *val *= sign;
168
      *pcur = cur;
169
      return TRUE;
170
   }
171
 
172
   return FALSE;
173
}
174
 
175
static boolean parse_identifier( const char **pcur, char *ret )
176
{
177
   const char *cur = *pcur;
178
   int i = 0;
179
   if (is_alpha_underscore( cur )) {
180
      ret[i++] = *cur++;
181
      while (is_alpha_underscore( cur ) || is_digit( cur ))
182
         ret[i++] = *cur++;
183
      ret[i++] = '\0';
184
      *pcur = cur;
185
      return TRUE;
186
   }
187
   return FALSE;
188
}
189
 
190
/* Parse floating point.
191
 */
192
static boolean parse_float( const char **pcur, float *val )
193
{
194
   const char *cur = *pcur;
195
   boolean integral_part = FALSE;
196
   boolean fractional_part = FALSE;
197
 
198
   *val = (float) atof( cur );
199
 
200
   if (*cur == '-' || *cur == '+')
201
      cur++;
202
   if (is_digit( cur )) {
203
      cur++;
204
      integral_part = TRUE;
205
      while (is_digit( cur ))
206
         cur++;
207
   }
208
   if (*cur == '.') {
209
      cur++;
210
      if (is_digit( cur )) {
211
         cur++;
212
         fractional_part = TRUE;
213
         while (is_digit( cur ))
214
            cur++;
215
      }
216
   }
217
   if (!integral_part && !fractional_part)
218
      return FALSE;
219
   if (uprcase( *cur ) == 'E') {
220
      cur++;
221
      if (*cur == '-' || *cur == '+')
222
         cur++;
223
      if (is_digit( cur )) {
224
         cur++;
225
         while (is_digit( cur ))
226
            cur++;
227
      }
228
      else
229
         return FALSE;
230
   }
231
   *pcur = cur;
232
   return TRUE;
233
}
234
 
235
struct translate_ctx
236
{
237
   const char *text;
238
   const char *cur;
239
   struct tgsi_token *tokens;
240
   struct tgsi_token *tokens_cur;
241
   struct tgsi_token *tokens_end;
242
   struct tgsi_header *header;
243
   unsigned processor : 4;
244
   int implied_array_size : 5;
245
   unsigned num_immediates;
246
};
247
 
248
static void report_error( struct translate_ctx *ctx, const char *msg )
249
{
250
   int line = 1;
251
   int column = 1;
252
   const char *itr = ctx->text;
253
 
254
   while (itr != ctx->cur) {
255
      if (*itr == '\n') {
256
         column = 1;
257
         ++line;
258
      }
259
      ++column;
260
      ++itr;
261
   }
262
 
263
   debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
264
}
265
 
266
/* Parse shader header.
267
 * Return TRUE for one of the following headers.
268
 *    FRAG
269
 *    GEOM
270
 *    VERT
271
 */
272
static boolean parse_header( struct translate_ctx *ctx )
273
{
274
   uint processor;
275
 
276
   if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
277
      processor = TGSI_PROCESSOR_FRAGMENT;
278
   else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
279
      processor = TGSI_PROCESSOR_VERTEX;
280
   else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
281
      processor = TGSI_PROCESSOR_GEOMETRY;
282
   else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
283
      processor = TGSI_PROCESSOR_COMPUTE;
284
   else {
285
      report_error( ctx, "Unknown header" );
286
      return FALSE;
287
   }
288
 
289
   if (ctx->tokens_cur >= ctx->tokens_end)
290
      return FALSE;
291
   ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
292
   *ctx->header = tgsi_build_header();
293
 
294
   if (ctx->tokens_cur >= ctx->tokens_end)
295
      return FALSE;
296
   *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
297
   ctx->processor = processor;
298
 
299
   return TRUE;
300
}
301
 
302
static boolean parse_label( struct translate_ctx *ctx, uint *val )
303
{
304
   const char *cur = ctx->cur;
305
 
306
   if (parse_uint( &cur, val )) {
307
      eat_opt_white( &cur );
308
      if (*cur == ':') {
309
         cur++;
310
         ctx->cur = cur;
311
         return TRUE;
312
      }
313
   }
314
   return FALSE;
315
}
316
 
317
static boolean
318
parse_file( const char **pcur, uint *file )
319
{
320
   uint i;
321
 
322
   for (i = 0; i < TGSI_FILE_COUNT; i++) {
323
      const char *cur = *pcur;
324
 
325
      if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) {
326
         *pcur = cur;
327
         *file = i;
328
         return TRUE;
329
      }
330
   }
331
   return FALSE;
332
}
333
 
334
static boolean
335
parse_opt_writemask(
336
   struct translate_ctx *ctx,
337
   uint *writemask )
338
{
339
   const char *cur;
340
 
341
   cur = ctx->cur;
342
   eat_opt_white( &cur );
343
   if (*cur == '.') {
344
      cur++;
345
      *writemask = TGSI_WRITEMASK_NONE;
346
      eat_opt_white( &cur );
347
      if (uprcase( *cur ) == 'X') {
348
         cur++;
349
         *writemask |= TGSI_WRITEMASK_X;
350
      }
351
      if (uprcase( *cur ) == 'Y') {
352
         cur++;
353
         *writemask |= TGSI_WRITEMASK_Y;
354
      }
355
      if (uprcase( *cur ) == 'Z') {
356
         cur++;
357
         *writemask |= TGSI_WRITEMASK_Z;
358
      }
359
      if (uprcase( *cur ) == 'W') {
360
         cur++;
361
         *writemask |= TGSI_WRITEMASK_W;
362
      }
363
 
364
      if (*writemask == TGSI_WRITEMASK_NONE) {
365
         report_error( ctx, "Writemask expected" );
366
         return FALSE;
367
      }
368
 
369
      ctx->cur = cur;
370
   }
371
   else {
372
      *writemask = TGSI_WRITEMASK_XYZW;
373
   }
374
   return TRUE;
375
}
376
 
377
 
378
/*  ::=  `['
379
 */
380
static boolean
381
parse_register_file_bracket(
382
   struct translate_ctx *ctx,
383
   uint *file )
384
{
385
   if (!parse_file( &ctx->cur, file )) {
386
      report_error( ctx, "Unknown register file" );
387
      return FALSE;
388
   }
389
   eat_opt_white( &ctx->cur );
390
   if (*ctx->cur != '[') {
391
      report_error( ctx, "Expected `['" );
392
      return FALSE;
393
   }
394
   ctx->cur++;
395
   return TRUE;
396
}
397
 
398
/*  ::=  
399
 */
400
static boolean
401
parse_register_file_bracket_index(
402
   struct translate_ctx *ctx,
403
   uint *file,
404
   int *index )
405
{
406
   uint uindex;
407
 
408
   if (!parse_register_file_bracket( ctx, file ))
409
      return FALSE;
410
   eat_opt_white( &ctx->cur );
411
   if (!parse_uint( &ctx->cur, &uindex )) {
412
      report_error( ctx, "Expected literal unsigned integer" );
413
      return FALSE;
414
   }
415
   *index = (int) uindex;
416
   return TRUE;
417
}
418
 
419
/* Parse simple 1d register operand.
420
 *     ::=  `]'
421
 */
422
static boolean
423
parse_register_1d(struct translate_ctx *ctx,
424
                  uint *file,
425
                  int *index )
426
{
427
   if (!parse_register_file_bracket_index( ctx, file, index ))
428
      return FALSE;
429
   eat_opt_white( &ctx->cur );
430
   if (*ctx->cur != ']') {
431
      report_error( ctx, "Expected `]'" );
432
      return FALSE;
433
   }
434
   ctx->cur++;
435
   return TRUE;
436
}
437
 
438
struct parsed_bracket {
439
   int index;
440
 
441
   uint ind_file;
442
   int ind_index;
443
   uint ind_comp;
444
   uint ind_array;
445
};
446
 
447
 
448
static boolean
449
parse_register_bracket(
450
   struct translate_ctx *ctx,
451
   struct parsed_bracket *brackets)
452
{
453
   const char *cur;
454
   uint uindex;
455
 
456
   memset(brackets, 0, sizeof(struct parsed_bracket));
457
 
458
   eat_opt_white( &ctx->cur );
459
 
460
   cur = ctx->cur;
461
   if (parse_file( &cur, &brackets->ind_file )) {
462
      if (!parse_register_1d( ctx, &brackets->ind_file,
463
                              &brackets->ind_index ))
464
         return FALSE;
465
      eat_opt_white( &ctx->cur );
466
 
467
      if (*ctx->cur == '.') {
468
         ctx->cur++;
469
         eat_opt_white(&ctx->cur);
470
 
471
         switch (uprcase(*ctx->cur)) {
472
         case 'X':
473
            brackets->ind_comp = TGSI_SWIZZLE_X;
474
            break;
475
         case 'Y':
476
            brackets->ind_comp = TGSI_SWIZZLE_Y;
477
            break;
478
         case 'Z':
479
            brackets->ind_comp = TGSI_SWIZZLE_Z;
480
            break;
481
         case 'W':
482
            brackets->ind_comp = TGSI_SWIZZLE_W;
483
            break;
484
         default:
485
            report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
486
            return FALSE;
487
         }
488
         ctx->cur++;
489
         eat_opt_white(&ctx->cur);
490
      }
491
 
492
      if (*ctx->cur == '+' || *ctx->cur == '-')
493
         parse_int( &ctx->cur, &brackets->index );
494
      else
495
         brackets->index = 0;
496
   }
497
   else {
498
      if (!parse_uint( &ctx->cur, &uindex )) {
499
         report_error( ctx, "Expected literal unsigned integer" );
500
         return FALSE;
501
      }
502
      brackets->index = (int) uindex;
503
      brackets->ind_file = TGSI_FILE_NULL;
504
      brackets->ind_index = 0;
505
   }
506
   eat_opt_white( &ctx->cur );
507
   if (*ctx->cur != ']') {
508
      report_error( ctx, "Expected `]'" );
509
      return FALSE;
510
   }
511
   ctx->cur++;
512
   if (*ctx->cur == '(') {
513
      ctx->cur++;
514
      eat_opt_white( &ctx->cur );
515
      if (!parse_uint( &ctx->cur, &brackets->ind_array )) {
516
         report_error( ctx, "Expected literal unsigned integer" );
517
         return FALSE;
518
      }
519
      eat_opt_white( &ctx->cur );
520
      if (*ctx->cur != ')') {
521
         report_error( ctx, "Expected `)'" );
522
         return FALSE;
523
      }
524
      ctx->cur++;
525
   }
526
   return TRUE;
527
}
528
 
529
static boolean
530
parse_opt_register_src_bracket(
531
   struct translate_ctx *ctx,
532
   struct parsed_bracket *brackets,
533
   int *parsed_brackets)
534
{
535
   const char *cur = ctx->cur;
536
 
537
   *parsed_brackets = 0;
538
 
539
   eat_opt_white( &cur );
540
   if (cur[0] == '[') {
541
      ++cur;
542
      ctx->cur = cur;
543
 
544
      if (!parse_register_bracket(ctx, brackets))
545
         return FALSE;
546
 
547
      *parsed_brackets = 1;
548
   }
549
 
550
   return TRUE;
551
}
552
 
553
 
554
/* Parse source register operand.
555
 *     ::=  `]' |
556
 *                         [`.' (`x' | `y' | `z' | `w')] `]' |
557
 *                         [`.' (`x' | `y' | `z' | `w')] `+'  `]' |
558
 *                         [`.' (`x' | `y' | `z' | `w')] `-'  `]'
559
 */
560
static boolean
561
parse_register_src(
562
   struct translate_ctx *ctx,
563
   uint *file,
564
   struct parsed_bracket *brackets)
565
{
566
   brackets->ind_comp = TGSI_SWIZZLE_X;
567
   if (!parse_register_file_bracket( ctx, file ))
568
      return FALSE;
569
   if (!parse_register_bracket( ctx, brackets ))
570
       return FALSE;
571
 
572
   return TRUE;
573
}
574
 
575
struct parsed_dcl_bracket {
576
   uint first;
577
   uint last;
578
};
579
 
580
static boolean
581
parse_register_dcl_bracket(
582
   struct translate_ctx *ctx,
583
   struct parsed_dcl_bracket *bracket)
584
{
585
   uint uindex;
586
   memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
587
 
588
   eat_opt_white( &ctx->cur );
589
 
590
   if (!parse_uint( &ctx->cur, &uindex )) {
591
      /* it can be an empty bracket [] which means its range
592
       * is from 0 to some implied size */
593
      if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
594
         bracket->first = 0;
595
         bracket->last = ctx->implied_array_size - 1;
596
         goto cleanup;
597
      }
598
      report_error( ctx, "Expected literal unsigned integer" );
599
      return FALSE;
600
   }
601
   bracket->first = uindex;
602
 
603
   eat_opt_white( &ctx->cur );
604
 
605
   if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
606
      uint uindex;
607
 
608
      ctx->cur += 2;
609
      eat_opt_white( &ctx->cur );
610
      if (!parse_uint( &ctx->cur, &uindex )) {
611
         report_error( ctx, "Expected literal integer" );
612
         return FALSE;
613
      }
614
      bracket->last = (int) uindex;
615
      eat_opt_white( &ctx->cur );
616
   }
617
   else {
618
      bracket->last = bracket->first;
619
   }
620
 
621
cleanup:
622
   if (*ctx->cur != ']') {
623
      report_error( ctx, "Expected `]' or `..'" );
624
      return FALSE;
625
   }
626
   ctx->cur++;
627
   return TRUE;
628
}
629
 
630
/* Parse register declaration.
631
 *     ::=  `]' |
632
 *                        `..'  `]'
633
 */
634
static boolean
635
parse_register_dcl(
636
   struct translate_ctx *ctx,
637
   uint *file,
638
   struct parsed_dcl_bracket *brackets,
639
   int *num_brackets)
640
{
641
   const char *cur;
642
 
643
   *num_brackets = 0;
644
 
645
   if (!parse_register_file_bracket( ctx, file ))
646
      return FALSE;
647
   if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
648
      return FALSE;
649
 
650
   *num_brackets = 1;
651
 
652
   cur = ctx->cur;
653
   eat_opt_white( &cur );
654
 
655
   if (cur[0] == '[') {
656
      ++cur;
657
      ctx->cur = cur;
658
      if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
659
         return FALSE;
660
      /* for geometry shader we don't really care about
661
       * the first brackets it's always the size of the
662
       * input primitive. so we want to declare just
663
       * the index relevant to the semantics which is in
664
       * the second bracket */
665
      if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
666
         brackets[0] = brackets[1];
667
         *num_brackets = 1;
668
      } else {
669
         *num_brackets = 2;
670
      }
671
   }
672
 
673
   return TRUE;
674
}
675
 
676
 
677
/* Parse destination register operand.*/
678
static boolean
679
parse_register_dst(
680
   struct translate_ctx *ctx,
681
   uint *file,
682
   struct parsed_bracket *brackets)
683
{
684
   brackets->ind_comp = TGSI_SWIZZLE_X;
685
   if (!parse_register_file_bracket( ctx, file ))
686
      return FALSE;
687
   if (!parse_register_bracket( ctx, brackets ))
688
       return FALSE;
689
 
690
   return TRUE;
691
}
692
 
693
static boolean
694
parse_dst_operand(
695
   struct translate_ctx *ctx,
696
   struct tgsi_full_dst_register *dst )
697
{
698
   uint file;
699
   uint writemask;
700
   const char *cur;
701
   struct parsed_bracket bracket[2];
702
   int parsed_opt_brackets;
703
 
704
   if (!parse_register_dst( ctx, &file, &bracket[0] ))
705
      return FALSE;
706
   if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
707
      return FALSE;
708
 
709
   cur = ctx->cur;
710
   eat_opt_white( &cur );
711
 
712
   if (!parse_opt_writemask( ctx, &writemask ))
713
      return FALSE;
714
 
715
   dst->Register.File = file;
716
   if (parsed_opt_brackets) {
717
      dst->Register.Dimension = 1;
718
      dst->Dimension.Indirect = 0;
719
      dst->Dimension.Dimension = 0;
720
      dst->Dimension.Index = bracket[0].index;
721
      bracket[0] = bracket[1];
722
   }
723
   dst->Register.Index = bracket[0].index;
724
   dst->Register.WriteMask = writemask;
725
   if (bracket[0].ind_file != TGSI_FILE_NULL) {
726
      dst->Register.Indirect = 1;
727
      dst->Indirect.File = bracket[0].ind_file;
728
      dst->Indirect.Index = bracket[0].ind_index;
729
      dst->Indirect.Swizzle = bracket[0].ind_comp;
730
      dst->Indirect.ArrayID = bracket[0].ind_array;
731
   }
732
   return TRUE;
733
}
734
 
735
static boolean
736
parse_optional_swizzle(
737
   struct translate_ctx *ctx,
738
   uint swizzle[4],
739
   boolean *parsed_swizzle )
740
{
741
   const char *cur = ctx->cur;
742
 
743
   *parsed_swizzle = FALSE;
744
 
745
   eat_opt_white( &cur );
746
   if (*cur == '.') {
747
      uint i;
748
 
749
      cur++;
750
      eat_opt_white( &cur );
751
      for (i = 0; i < 4; i++) {
752
         if (uprcase( *cur ) == 'X')
753
            swizzle[i] = TGSI_SWIZZLE_X;
754
         else if (uprcase( *cur ) == 'Y')
755
            swizzle[i] = TGSI_SWIZZLE_Y;
756
         else if (uprcase( *cur ) == 'Z')
757
            swizzle[i] = TGSI_SWIZZLE_Z;
758
         else if (uprcase( *cur ) == 'W')
759
            swizzle[i] = TGSI_SWIZZLE_W;
760
         else {
761
	    report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
762
	    return FALSE;
763
         }
764
         cur++;
765
      }
766
      *parsed_swizzle = TRUE;
767
      ctx->cur = cur;
768
   }
769
   return TRUE;
770
}
771
 
772
static boolean
773
parse_src_operand(
774
   struct translate_ctx *ctx,
775
   struct tgsi_full_src_register *src )
776
{
777
   uint file;
778
   uint swizzle[4];
779
   boolean parsed_swizzle;
780
   struct parsed_bracket bracket[2];
781
   int parsed_opt_brackets;
782
 
783
   if (*ctx->cur == '-') {
784
      ctx->cur++;
785
      eat_opt_white( &ctx->cur );
786
      src->Register.Negate = 1;
787
   }
788
 
789
   if (*ctx->cur == '|') {
790
      ctx->cur++;
791
      eat_opt_white( &ctx->cur );
792
      src->Register.Absolute = 1;
793
   }
794
 
795
   if (!parse_register_src(ctx, &file, &bracket[0]))
796
      return FALSE;
797
   if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
798
      return FALSE;
799
 
800
   src->Register.File = file;
801
   if (parsed_opt_brackets) {
802
      src->Register.Dimension = 1;
803
      src->Dimension.Indirect = 0;
804
      src->Dimension.Dimension = 0;
805
      src->Dimension.Index = bracket[0].index;
806
      bracket[0] = bracket[1];
807
   }
808
   src->Register.Index = bracket[0].index;
809
   if (bracket[0].ind_file != TGSI_FILE_NULL) {
810
      src->Register.Indirect = 1;
811
      src->Indirect.File = bracket[0].ind_file;
812
      src->Indirect.Index = bracket[0].ind_index;
813
      src->Indirect.Swizzle = bracket[0].ind_comp;
814
      src->Indirect.ArrayID = bracket[0].ind_array;
815
   }
816
 
817
   /* Parse optional swizzle.
818
    */
819
   if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
820
      if (parsed_swizzle) {
821
         src->Register.SwizzleX = swizzle[0];
822
         src->Register.SwizzleY = swizzle[1];
823
         src->Register.SwizzleZ = swizzle[2];
824
         src->Register.SwizzleW = swizzle[3];
825
      }
826
   }
827
 
828
   if (src->Register.Absolute) {
829
      eat_opt_white( &ctx->cur );
830
      if (*ctx->cur != '|') {
831
         report_error( ctx, "Expected `|'" );
832
         return FALSE;
833
      }
834
      ctx->cur++;
835
   }
836
 
837
 
838
   return TRUE;
839
}
840
 
841
static boolean
842
match_inst(const char **pcur,
843
           unsigned *saturate,
844
           const struct tgsi_opcode_info *info)
845
{
846
   const char *cur = *pcur;
847
 
848
   /* simple case: the whole string matches the instruction name */
849
   if (str_match_nocase_whole(&cur, info->mnemonic)) {
850
      *pcur = cur;
851
      *saturate = TGSI_SAT_NONE;
852
      return TRUE;
853
   }
854
 
855
   if (str_match_no_case(&cur, info->mnemonic)) {
856
      /* the instruction has a suffix, figure it out */
857
      if (str_match_nocase_whole(&cur, "_SAT")) {
858
         *pcur = cur;
859
         *saturate = TGSI_SAT_ZERO_ONE;
860
         return TRUE;
861
      }
862
 
863
      if (str_match_nocase_whole(&cur, "_SATNV")) {
864
         *pcur = cur;
865
         *saturate = TGSI_SAT_MINUS_PLUS_ONE;
866
         return TRUE;
867
      }
868
   }
869
 
870
   return FALSE;
871
}
872
 
873
static boolean
874
parse_instruction(
875
   struct translate_ctx *ctx,
876
   boolean has_label )
877
{
878
   uint i;
879
   uint saturate = TGSI_SAT_NONE;
880
   const struct tgsi_opcode_info *info;
881
   struct tgsi_full_instruction inst;
882
   const char *cur;
883
   uint advance;
884
 
885
   inst = tgsi_default_full_instruction();
886
 
887
   /* Parse predicate.
888
    */
889
   eat_opt_white( &ctx->cur );
890
   if (*ctx->cur == '(') {
891
      uint file;
892
      int index;
893
      uint swizzle[4];
894
      boolean parsed_swizzle;
895
 
896
      inst.Instruction.Predicate = 1;
897
 
898
      ctx->cur++;
899
      if (*ctx->cur == '!') {
900
         ctx->cur++;
901
         inst.Predicate.Negate = 1;
902
      }
903
 
904
      if (!parse_register_1d( ctx, &file, &index ))
905
         return FALSE;
906
 
907
      if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
908
         if (parsed_swizzle) {
909
            inst.Predicate.SwizzleX = swizzle[0];
910
            inst.Predicate.SwizzleY = swizzle[1];
911
            inst.Predicate.SwizzleZ = swizzle[2];
912
            inst.Predicate.SwizzleW = swizzle[3];
913
         }
914
      }
915
 
916
      if (*ctx->cur != ')') {
917
         report_error( ctx, "Expected `)'" );
918
         return FALSE;
919
      }
920
 
921
      ctx->cur++;
922
   }
923
 
924
   /* Parse instruction name.
925
    */
926
   eat_opt_white( &ctx->cur );
927
   for (i = 0; i < TGSI_OPCODE_LAST; i++) {
928
      cur = ctx->cur;
929
 
930
      info = tgsi_get_opcode_info( i );
931
      if (match_inst(&cur, &saturate, info)) {
932
         if (info->num_dst + info->num_src + info->is_tex == 0) {
933
            ctx->cur = cur;
934
            break;
935
         }
936
         else if (*cur == '\0' || eat_white( &cur )) {
937
            ctx->cur = cur;
938
            break;
939
         }
940
      }
941
   }
942
   if (i == TGSI_OPCODE_LAST) {
943
      if (has_label)
944
         report_error( ctx, "Unknown opcode" );
945
      else
946
         report_error( ctx, "Expected `DCL', `IMM' or a label" );
947
      return FALSE;
948
   }
949
 
950
   inst.Instruction.Opcode = i;
951
   inst.Instruction.Saturate = saturate;
952
   inst.Instruction.NumDstRegs = info->num_dst;
953
   inst.Instruction.NumSrcRegs = info->num_src;
954
 
955
   if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
956
      /*
957
       * These are not considered tex opcodes here (no additional
958
       * target argument) however we're required to set the Texture
959
       * bit so we can set the number of tex offsets (offsets aren't
960
       * actually handled here yet in any case).
961
       */
962
      inst.Instruction.Texture = 1;
963
      inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
964
   }
965
 
966
   /* Parse instruction operands.
967
    */
968
   for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
969
      if (i > 0) {
970
         eat_opt_white( &ctx->cur );
971
         if (*ctx->cur != ',') {
972
            report_error( ctx, "Expected `,'" );
973
            return FALSE;
974
         }
975
         ctx->cur++;
976
         eat_opt_white( &ctx->cur );
977
      }
978
 
979
      if (i < info->num_dst) {
980
         if (!parse_dst_operand( ctx, &inst.Dst[i] ))
981
            return FALSE;
982
      }
983
      else if (i < info->num_dst + info->num_src) {
984
         if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
985
            return FALSE;
986
      }
987
      else {
988
         uint j;
989
 
990
         for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
991
            if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
992
               inst.Instruction.Texture = 1;
993
               inst.Texture.Texture = j;
994
               break;
995
            }
996
         }
997
         if (j == TGSI_TEXTURE_COUNT) {
998
            report_error( ctx, "Expected texture target" );
999
            return FALSE;
1000
         }
1001
      }
1002
   }
1003
 
1004
   cur = ctx->cur;
1005
   eat_opt_white( &cur );
1006
   if (info->is_branch && *cur == ':') {
1007
      uint target;
1008
 
1009
      cur++;
1010
      eat_opt_white( &cur );
1011
      if (!parse_uint( &cur, &target )) {
1012
         report_error( ctx, "Expected a label" );
1013
         return FALSE;
1014
      }
1015
      inst.Instruction.Label = 1;
1016
      inst.Label.Label = target;
1017
      ctx->cur = cur;
1018
   }
1019
 
1020
   advance = tgsi_build_full_instruction(
1021
      &inst,
1022
      ctx->tokens_cur,
1023
      ctx->header,
1024
      (uint) (ctx->tokens_end - ctx->tokens_cur) );
1025
   if (advance == 0)
1026
      return FALSE;
1027
   ctx->tokens_cur += advance;
1028
 
1029
   return TRUE;
1030
}
1031
 
1032
/* parses a 4-touple of the form {x, y, z, w}
1033
 * where x, y, z, w are numbers */
1034
static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
1035
                                    union tgsi_immediate_data *values)
1036
{
1037
   unsigned i;
1038
   int ret;
1039
 
1040
   eat_opt_white( &ctx->cur );
1041
   if (*ctx->cur != '{') {
1042
      report_error( ctx, "Expected `{'" );
1043
      return FALSE;
1044
   }
1045
   ctx->cur++;
1046
   for (i = 0; i < 4; i++) {
1047
      eat_opt_white( &ctx->cur );
1048
      if (i > 0) {
1049
         if (*ctx->cur != ',') {
1050
            report_error( ctx, "Expected `,'" );
1051
            return FALSE;
1052
         }
1053
         ctx->cur++;
1054
         eat_opt_white( &ctx->cur );
1055
      }
1056
 
1057
      switch (type) {
1058
      case TGSI_IMM_FLOAT32:
1059
         ret = parse_float(&ctx->cur, &values[i].Float);
1060
         break;
1061
      case TGSI_IMM_UINT32:
1062
         ret = parse_uint(&ctx->cur, &values[i].Uint);
1063
         break;
1064
      case TGSI_IMM_INT32:
1065
         ret = parse_int(&ctx->cur, &values[i].Int);
1066
         break;
1067
      default:
1068
         assert(0);
1069
         ret = FALSE;
1070
         break;
1071
      }
1072
 
1073
      if (!ret) {
1074
         report_error( ctx, "Expected immediate constant" );
1075
         return FALSE;
1076
      }
1077
   }
1078
   eat_opt_white( &ctx->cur );
1079
   if (*ctx->cur != '}') {
1080
      report_error( ctx, "Expected `}'" );
1081
      return FALSE;
1082
   }
1083
   ctx->cur++;
1084
 
1085
   return TRUE;
1086
}
1087
 
1088
static boolean parse_declaration( struct translate_ctx *ctx )
1089
{
1090
   struct tgsi_full_declaration decl;
1091
   uint file;
1092
   struct parsed_dcl_bracket brackets[2];
1093
   int num_brackets;
1094
   uint writemask;
1095
   const char *cur, *cur2;
1096
   uint advance;
1097
   boolean is_vs_input;
1098
 
1099
   if (!eat_white( &ctx->cur )) {
1100
      report_error( ctx, "Syntax error" );
1101
      return FALSE;
1102
   }
1103
   if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1104
      return FALSE;
1105
   if (!parse_opt_writemask( ctx, &writemask ))
1106
      return FALSE;
1107
 
1108
   decl = tgsi_default_full_declaration();
1109
   decl.Declaration.File = file;
1110
   decl.Declaration.UsageMask = writemask;
1111
 
1112
   if (num_brackets == 1) {
1113
      decl.Range.First = brackets[0].first;
1114
      decl.Range.Last = brackets[0].last;
1115
   } else {
1116
      decl.Range.First = brackets[1].first;
1117
      decl.Range.Last = brackets[1].last;
1118
 
1119
      decl.Declaration.Dimension = 1;
1120
      decl.Dim.Index2D = brackets[0].first;
1121
   }
1122
 
1123
   is_vs_input = (file == TGSI_FILE_INPUT &&
1124
                  ctx->processor == TGSI_PROCESSOR_VERTEX);
1125
 
1126
   cur = ctx->cur;
1127
   eat_opt_white( &cur );
1128
   if (*cur == ',') {
1129
      cur2 = cur;
1130
      cur2++;
1131
      eat_opt_white( &cur2 );
1132
      if (str_match_nocase_whole( &cur2, "ARRAY" )) {
1133
         int arrayid;
1134
         if (*cur2 != '(') {
1135
            report_error( ctx, "Expected `('" );
1136
            return FALSE;
1137
         }
1138
         cur2++;
1139
         eat_opt_white( &cur2 );
1140
         if (!parse_int( &cur2, &arrayid )) {
1141
            report_error( ctx, "Expected `,'" );
1142
            return FALSE;
1143
         }
1144
         eat_opt_white( &cur2 );
1145
         if (*cur2 != ')') {
1146
            report_error( ctx, "Expected `)'" );
1147
            return FALSE;
1148
         }
1149
         cur2++;
1150
         decl.Declaration.Array = 1;
1151
         decl.Array.ArrayID = arrayid;
1152
         ctx->cur = cur = cur2;
1153
      }
1154
   }
1155
 
1156
   if (*cur == ',' && !is_vs_input) {
1157
      uint i, j;
1158
 
1159
      cur++;
1160
      eat_opt_white( &cur );
1161
      if (file == TGSI_FILE_RESOURCE) {
1162
         for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1163
            if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1164
               decl.Resource.Resource = i;
1165
               break;
1166
            }
1167
         }
1168
         if (i == TGSI_TEXTURE_COUNT) {
1169
            report_error(ctx, "Expected texture target");
1170
            return FALSE;
1171
         }
1172
 
1173
         cur2 = cur;
1174
         eat_opt_white(&cur2);
1175
         while (*cur2 == ',') {
1176
            cur2++;
1177
            eat_opt_white(&cur2);
1178
            if (str_match_nocase_whole(&cur2, "RAW")) {
1179
               decl.Resource.Raw = 1;
1180
 
1181
            } else if (str_match_nocase_whole(&cur2, "WR")) {
1182
               decl.Resource.Writable = 1;
1183
 
1184
            } else {
1185
               break;
1186
            }
1187
            cur = cur2;
1188
            eat_opt_white(&cur2);
1189
         }
1190
 
1191
         ctx->cur = cur;
1192
 
1193
      } else if (file == TGSI_FILE_SAMPLER_VIEW) {
1194
         for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1195
            if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1196
               decl.SamplerView.Resource = i;
1197
               break;
1198
            }
1199
         }
1200
         if (i == TGSI_TEXTURE_COUNT) {
1201
            report_error(ctx, "Expected texture target");
1202
            return FALSE;
1203
         }
1204
         eat_opt_white( &cur );
1205
         if (*cur != ',') {
1206
            report_error( ctx, "Expected `,'" );
1207
            return FALSE;
1208
         }
1209
         ++cur;
1210
         eat_opt_white( &cur );
1211
         for (j = 0; j < 4; ++j) {
1212
            for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
1213
               if (str_match_nocase_whole(&cur, tgsi_type_names[i])) {
1214
                  switch (j) {
1215
                  case 0:
1216
                     decl.SamplerView.ReturnTypeX = i;
1217
                     break;
1218
                  case 1:
1219
                     decl.SamplerView.ReturnTypeY = i;
1220
                     break;
1221
                  case 2:
1222
                     decl.SamplerView.ReturnTypeZ = i;
1223
                     break;
1224
                  case 3:
1225
                     decl.SamplerView.ReturnTypeW = i;
1226
                     break;
1227
                  default:
1228
                     assert(0);
1229
                  }
1230
                  break;
1231
               }
1232
            }
1233
            if (i == PIPE_TYPE_COUNT) {
1234
               if (j == 0 || j >  2) {
1235
                  report_error(ctx, "Expected type name");
1236
                  return FALSE;
1237
               }
1238
               break;
1239
            } else {
1240
               cur2 = cur;
1241
               eat_opt_white( &cur2 );
1242
               if (*cur2 == ',') {
1243
                  cur2++;
1244
                  eat_opt_white( &cur2 );
1245
                  cur = cur2;
1246
                  continue;
1247
               } else
1248
                  break;
1249
            }
1250
         }
1251
         if (j < 4) {
1252
            decl.SamplerView.ReturnTypeY =
1253
               decl.SamplerView.ReturnTypeZ =
1254
               decl.SamplerView.ReturnTypeW =
1255
               decl.SamplerView.ReturnTypeX;
1256
         }
1257
         ctx->cur = cur;
1258
      } else {
1259
         if (str_match_nocase_whole(&cur, "LOCAL")) {
1260
            decl.Declaration.Local = 1;
1261
            ctx->cur = cur;
1262
         }
1263
 
1264
         cur = ctx->cur;
1265
         eat_opt_white( &cur );
1266
         if (*cur == ',') {
1267
            cur++;
1268
            eat_opt_white( &cur );
1269
 
1270
            for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1271
               if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
1272
                  uint index;
1273
 
1274
                  cur2 = cur;
1275
                  eat_opt_white( &cur2 );
1276
                  if (*cur2 == '[') {
1277
                     cur2++;
1278
                     eat_opt_white( &cur2 );
1279
                     if (!parse_uint( &cur2, &index )) {
1280
                        report_error( ctx, "Expected literal integer" );
1281
                        return FALSE;
1282
                     }
1283
                     eat_opt_white( &cur2 );
1284
                     if (*cur2 != ']') {
1285
                        report_error( ctx, "Expected `]'" );
1286
                        return FALSE;
1287
                     }
1288
                     cur2++;
1289
 
1290
                     decl.Semantic.Index = index;
1291
 
1292
                     cur = cur2;
1293
                  }
1294
 
1295
                  decl.Declaration.Semantic = 1;
1296
                  decl.Semantic.Name = i;
1297
 
1298
                  ctx->cur = cur;
1299
                  break;
1300
               }
1301
            }
1302
         }
1303
      }
1304
   }
1305
 
1306
   cur = ctx->cur;
1307
   eat_opt_white( &cur );
1308
   if (*cur == ',' && !is_vs_input) {
1309
      uint i;
1310
 
1311
      cur++;
1312
      eat_opt_white( &cur );
1313
      for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1314
         if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
1315
            decl.Declaration.Interpolate = 1;
1316
            decl.Interp.Interpolate = i;
1317
 
1318
            ctx->cur = cur;
1319
            break;
1320
         }
1321
      }
1322
      if (i == TGSI_INTERPOLATE_COUNT) {
1323
         report_error( ctx, "Expected semantic or interpolate attribute" );
1324
         return FALSE;
1325
      }
1326
   }
1327
 
1328
   advance = tgsi_build_full_declaration(
1329
      &decl,
1330
      ctx->tokens_cur,
1331
      ctx->header,
1332
      (uint) (ctx->tokens_end - ctx->tokens_cur) );
1333
 
1334
   if (advance == 0)
1335
      return FALSE;
1336
   ctx->tokens_cur += advance;
1337
 
1338
   return TRUE;
1339
}
1340
 
1341
static boolean parse_immediate( struct translate_ctx *ctx )
1342
{
1343
   struct tgsi_full_immediate imm;
1344
   uint advance;
1345
   int type;
1346
 
1347
   if (*ctx->cur == '[') {
1348
      uint uindex;
1349
 
1350
      ++ctx->cur;
1351
 
1352
      eat_opt_white( &ctx->cur );
1353
      if (!parse_uint( &ctx->cur, &uindex )) {
1354
         report_error( ctx, "Expected literal unsigned integer" );
1355
         return FALSE;
1356
      }
1357
 
1358
      if (uindex != ctx->num_immediates) {
1359
         report_error( ctx, "Immediates must be sorted" );
1360
         return FALSE;
1361
      }
1362
 
1363
      eat_opt_white( &ctx->cur );
1364
      if (*ctx->cur != ']') {
1365
         report_error( ctx, "Expected `]'" );
1366
         return FALSE;
1367
      }
1368
 
1369
      ctx->cur++;
1370
   }
1371
 
1372
   if (!eat_white( &ctx->cur )) {
1373
      report_error( ctx, "Syntax error" );
1374
      return FALSE;
1375
   }
1376
   for (type = 0; type < Elements(tgsi_immediate_type_names); ++type) {
1377
      if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
1378
         break;
1379
   }
1380
   if (type == Elements(tgsi_immediate_type_names)) {
1381
      report_error( ctx, "Expected immediate type" );
1382
      return FALSE;
1383
   }
1384
 
1385
   imm = tgsi_default_full_immediate();
1386
   imm.Immediate.NrTokens += 4;
1387
   imm.Immediate.DataType = type;
1388
   parse_immediate_data(ctx, type, imm.u);
1389
 
1390
   advance = tgsi_build_full_immediate(
1391
      &imm,
1392
      ctx->tokens_cur,
1393
      ctx->header,
1394
      (uint) (ctx->tokens_end - ctx->tokens_cur) );
1395
   if (advance == 0)
1396
      return FALSE;
1397
   ctx->tokens_cur += advance;
1398
 
1399
   ctx->num_immediates++;
1400
 
1401
   return TRUE;
1402
}
1403
 
1404
static boolean
1405
parse_primitive( const char **pcur, uint *primitive )
1406
{
1407
   uint i;
1408
 
1409
   for (i = 0; i < PIPE_PRIM_MAX; i++) {
1410
      const char *cur = *pcur;
1411
 
1412
      if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
1413
         *primitive = i;
1414
         *pcur = cur;
1415
         return TRUE;
1416
      }
1417
   }
1418
   return FALSE;
1419
}
1420
 
1421
static boolean
1422
parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1423
{
1424
   uint i;
1425
 
1426
   for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
1427
      const char *cur = *pcur;
1428
 
1429
      if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
1430
         *fs_coord_origin = i;
1431
         *pcur = cur;
1432
         return TRUE;
1433
      }
1434
   }
1435
   return FALSE;
1436
}
1437
 
1438
static boolean
1439
parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1440
{
1441
   uint i;
1442
 
1443
   for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
1444
      const char *cur = *pcur;
1445
 
1446
      if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
1447
         *fs_coord_pixel_center = i;
1448
         *pcur = cur;
1449
         return TRUE;
1450
      }
1451
   }
1452
   return FALSE;
1453
}
1454
 
1455
 
1456
static boolean parse_property( struct translate_ctx *ctx )
1457
{
1458
   struct tgsi_full_property prop;
1459
   uint property_name;
1460
   uint values[8];
1461
   uint advance;
1462
   char id[64];
1463
 
1464
   if (!eat_white( &ctx->cur )) {
1465
      report_error( ctx, "Syntax error" );
1466
      return FALSE;
1467
   }
1468
   if (!parse_identifier( &ctx->cur, id )) {
1469
      report_error( ctx, "Syntax error" );
1470
      return FALSE;
1471
   }
1472
   for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1473
        ++property_name) {
1474
      if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
1475
         break;
1476
      }
1477
   }
1478
   if (property_name >= TGSI_PROPERTY_COUNT) {
1479
      debug_printf( "\nError: Unknown property : '%s'", id );
1480
      return FALSE;
1481
   }
1482
 
1483
   eat_opt_white( &ctx->cur );
1484
   switch(property_name) {
1485
   case TGSI_PROPERTY_GS_INPUT_PRIM:
1486
   case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1487
      if (!parse_primitive(&ctx->cur, &values[0] )) {
1488
         report_error( ctx, "Unknown primitive name as property!" );
1489
         return FALSE;
1490
      }
1491
      if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1492
          ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
1493
         ctx->implied_array_size = u_vertices_per_prim(values[0]);
1494
      }
1495
      break;
1496
   case TGSI_PROPERTY_FS_COORD_ORIGIN:
1497
      if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1498
         report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1499
         return FALSE;
1500
      }
1501
      break;
1502
   case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1503
      if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1504
         report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1505
         return FALSE;
1506
      }
1507
      break;
1508
   case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
1509
   default:
1510
      if (!parse_uint(&ctx->cur, &values[0] )) {
1511
         report_error( ctx, "Expected unsigned integer as property!" );
1512
         return FALSE;
1513
      }
1514
   }
1515
 
1516
   prop = tgsi_default_full_property();
1517
   prop.Property.PropertyName = property_name;
1518
   prop.Property.NrTokens += 1;
1519
   prop.u[0].Data = values[0];
1520
 
1521
   advance = tgsi_build_full_property(
1522
      &prop,
1523
      ctx->tokens_cur,
1524
      ctx->header,
1525
      (uint) (ctx->tokens_end - ctx->tokens_cur) );
1526
   if (advance == 0)
1527
      return FALSE;
1528
   ctx->tokens_cur += advance;
1529
 
1530
   return TRUE;
1531
}
1532
 
1533
 
1534
static boolean translate( struct translate_ctx *ctx )
1535
{
1536
   eat_opt_white( &ctx->cur );
1537
   if (!parse_header( ctx ))
1538
      return FALSE;
1539
 
1540
   while (*ctx->cur != '\0') {
1541
      uint label_val = 0;
1542
      if (!eat_white( &ctx->cur )) {
1543
         report_error( ctx, "Syntax error" );
1544
         return FALSE;
1545
      }
1546
 
1547
      if (*ctx->cur == '\0')
1548
         break;
1549
      if (parse_label( ctx, &label_val )) {
1550
         if (!parse_instruction( ctx, TRUE ))
1551
            return FALSE;
1552
      }
1553
      else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
1554
         if (!parse_declaration( ctx ))
1555
            return FALSE;
1556
      }
1557
      else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
1558
         if (!parse_immediate( ctx ))
1559
            return FALSE;
1560
      }
1561
      else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
1562
         if (!parse_property( ctx ))
1563
            return FALSE;
1564
      }
1565
      else if (!parse_instruction( ctx, FALSE )) {
1566
         return FALSE;
1567
      }
1568
   }
1569
 
1570
   return TRUE;
1571
}
1572
 
1573
boolean
1574
tgsi_text_translate(
1575
   const char *text,
1576
   struct tgsi_token *tokens,
1577
   uint num_tokens )
1578
{
1579
   struct translate_ctx ctx = {0};
1580
 
1581
   ctx.text = text;
1582
   ctx.cur = text;
1583
   ctx.tokens = tokens;
1584
   ctx.tokens_cur = tokens;
1585
   ctx.tokens_end = tokens + num_tokens;
1586
 
1587
   if (!translate( &ctx ))
1588
      return FALSE;
1589
 
1590
   return tgsi_sanity_check( tokens );
1591
}