Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/auxiliary/tgsi/tgsi_text.c
4565 views
1
/**************************************************************************
2
*
3
* Copyright 2008 VMware, Inc.
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 VMWARE 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
/* Return the array index that matches starting at *pcur, where the string at
123
* *pcur is terminated by a non-digit non-letter non-underscore.
124
* Returns -1 if no match is found.
125
*
126
* On success, the pointer to the first string is moved to the end of the read
127
* word.
128
*/
129
static int str_match_name_from_array(const char **pcur,
130
const char * const *array,
131
unsigned array_size)
132
{
133
for (unsigned j = 0; j < array_size; ++j) {
134
if (str_match_nocase_whole(pcur, array[j]))
135
return j;
136
}
137
return -1;
138
}
139
140
/* Return the format corresponding to the name at *pcur.
141
* Returns -1 if there is no format name.
142
*
143
* On success, the pointer to the string is moved to the end of the read format
144
* name.
145
*/
146
static int str_match_format(const char **pcur)
147
{
148
for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) {
149
const struct util_format_description *desc =
150
util_format_description(i);
151
if (desc && str_match_nocase_whole(pcur, desc->name)) {
152
return i;
153
}
154
}
155
return -1;
156
}
157
158
/* Eat zero or more whitespaces.
159
*/
160
static void eat_opt_white( const char **pcur )
161
{
162
while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
163
(*pcur)++;
164
}
165
166
/* Eat one or more whitespaces.
167
* Return TRUE if at least one whitespace eaten.
168
*/
169
static boolean eat_white( const char **pcur )
170
{
171
const char *cur = *pcur;
172
173
eat_opt_white( pcur );
174
return *pcur > cur;
175
}
176
177
/* Parse unsigned integer.
178
* No checks for overflow.
179
*/
180
static boolean parse_uint( const char **pcur, uint *val )
181
{
182
const char *cur = *pcur;
183
184
if (is_digit( cur )) {
185
*val = *cur++ - '0';
186
while (is_digit( cur ))
187
*val = *val * 10 + *cur++ - '0';
188
*pcur = cur;
189
return TRUE;
190
}
191
return FALSE;
192
}
193
194
static boolean parse_int( const char **pcur, int *val )
195
{
196
const char *cur = *pcur;
197
int sign = (*cur == '-' ? -1 : 1);
198
199
if (*cur == '+' || *cur == '-')
200
cur++;
201
202
if (parse_uint(&cur, (uint *)val)) {
203
*val *= sign;
204
*pcur = cur;
205
return TRUE;
206
}
207
208
return FALSE;
209
}
210
211
static boolean parse_identifier( const char **pcur, char *ret, size_t len )
212
{
213
const char *cur = *pcur;
214
size_t i = 0;
215
if (is_alpha_underscore( cur )) {
216
ret[i++] = *cur++;
217
while (is_alpha_underscore( cur ) || is_digit( cur )) {
218
if (i == len - 1)
219
return FALSE;
220
ret[i++] = *cur++;
221
}
222
ret[i++] = '\0';
223
*pcur = cur;
224
return TRUE;
225
}
226
return FALSE;
227
}
228
229
/* Parse floating point.
230
*/
231
static boolean parse_float( const char **pcur, float *val )
232
{
233
const char *cur = *pcur;
234
boolean integral_part = FALSE;
235
boolean fractional_part = FALSE;
236
237
if (*cur == '0' && *(cur + 1) == 'x') {
238
union fi fi;
239
fi.ui = strtoul(cur, NULL, 16);
240
*val = fi.f;
241
cur += 10;
242
goto out;
243
}
244
245
*val = (float) atof( cur );
246
if (*cur == '-' || *cur == '+')
247
cur++;
248
if (is_digit( cur )) {
249
cur++;
250
integral_part = TRUE;
251
while (is_digit( cur ))
252
cur++;
253
}
254
if (*cur == '.') {
255
cur++;
256
if (is_digit( cur )) {
257
cur++;
258
fractional_part = TRUE;
259
while (is_digit( cur ))
260
cur++;
261
}
262
}
263
if (!integral_part && !fractional_part)
264
return FALSE;
265
if (uprcase( *cur ) == 'E') {
266
cur++;
267
if (*cur == '-' || *cur == '+')
268
cur++;
269
if (is_digit( cur )) {
270
cur++;
271
while (is_digit( cur ))
272
cur++;
273
}
274
else
275
return FALSE;
276
}
277
278
out:
279
*pcur = cur;
280
return TRUE;
281
}
282
283
static boolean parse_double( const char **pcur, uint32_t *val0, uint32_t *val1)
284
{
285
const char *cur = *pcur;
286
union {
287
double dval;
288
uint32_t uval[2];
289
} v;
290
291
v.dval = strtod(cur, (char**)pcur);
292
if (*pcur == cur)
293
return FALSE;
294
295
*val0 = v.uval[0];
296
*val1 = v.uval[1];
297
298
return TRUE;
299
}
300
301
static boolean parse_int64( const char **pcur, uint32_t *val0, uint32_t *val1)
302
{
303
const char *cur = *pcur;
304
union {
305
int64_t i64val;
306
uint32_t uval[2];
307
} v;
308
309
v.i64val = strtoll(cur, (char**)pcur, 0);
310
if (*pcur == cur)
311
return FALSE;
312
313
*val0 = v.uval[0];
314
*val1 = v.uval[1];
315
316
return TRUE;
317
}
318
319
static boolean parse_uint64( const char **pcur, uint32_t *val0, uint32_t *val1)
320
{
321
const char *cur = *pcur;
322
union {
323
uint64_t u64val;
324
uint32_t uval[2];
325
} v;
326
327
v.u64val = strtoull(cur, (char**)pcur, 0);
328
if (*pcur == cur)
329
return FALSE;
330
331
*val0 = v.uval[0];
332
*val1 = v.uval[1];
333
334
return TRUE;
335
}
336
337
struct translate_ctx
338
{
339
const char *text;
340
const char *cur;
341
struct tgsi_token *tokens;
342
struct tgsi_token *tokens_cur;
343
struct tgsi_token *tokens_end;
344
struct tgsi_header *header;
345
unsigned processor : 4;
346
unsigned implied_array_size : 6;
347
unsigned num_immediates;
348
};
349
350
static void report_error( struct translate_ctx *ctx, const char *msg )
351
{
352
int line = 1;
353
int column = 1;
354
const char *itr = ctx->text;
355
356
while (itr != ctx->cur) {
357
if (*itr == '\n') {
358
column = 1;
359
++line;
360
}
361
++column;
362
++itr;
363
}
364
365
debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
366
}
367
368
/* Parse shader header.
369
* Return TRUE for one of the following headers.
370
* FRAG
371
* GEOM
372
* VERT
373
*/
374
static boolean parse_header( struct translate_ctx *ctx )
375
{
376
uint processor;
377
378
if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
379
processor = PIPE_SHADER_FRAGMENT;
380
else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
381
processor = PIPE_SHADER_VERTEX;
382
else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
383
processor = PIPE_SHADER_GEOMETRY;
384
else if (str_match_nocase_whole( &ctx->cur, "TESS_CTRL" ))
385
processor = PIPE_SHADER_TESS_CTRL;
386
else if (str_match_nocase_whole( &ctx->cur, "TESS_EVAL" ))
387
processor = PIPE_SHADER_TESS_EVAL;
388
else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
389
processor = PIPE_SHADER_COMPUTE;
390
else {
391
report_error( ctx, "Unknown header" );
392
return FALSE;
393
}
394
395
if (ctx->tokens_cur >= ctx->tokens_end)
396
return FALSE;
397
ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
398
*ctx->header = tgsi_build_header();
399
400
if (ctx->tokens_cur >= ctx->tokens_end)
401
return FALSE;
402
*(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
403
ctx->processor = processor;
404
405
return TRUE;
406
}
407
408
static boolean parse_label( struct translate_ctx *ctx, uint *val )
409
{
410
const char *cur = ctx->cur;
411
412
if (parse_uint( &cur, val )) {
413
eat_opt_white( &cur );
414
if (*cur == ':') {
415
cur++;
416
ctx->cur = cur;
417
return TRUE;
418
}
419
}
420
return FALSE;
421
}
422
423
static boolean
424
parse_file( const char **pcur, uint *file )
425
{
426
uint i;
427
428
for (i = 0; i < TGSI_FILE_COUNT; i++) {
429
const char *cur = *pcur;
430
431
if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) {
432
*pcur = cur;
433
*file = i;
434
return TRUE;
435
}
436
}
437
return FALSE;
438
}
439
440
static boolean
441
parse_opt_writemask(
442
struct translate_ctx *ctx,
443
uint *writemask )
444
{
445
const char *cur;
446
447
cur = ctx->cur;
448
eat_opt_white( &cur );
449
if (*cur == '.') {
450
cur++;
451
*writemask = TGSI_WRITEMASK_NONE;
452
eat_opt_white( &cur );
453
if (uprcase( *cur ) == 'X') {
454
cur++;
455
*writemask |= TGSI_WRITEMASK_X;
456
}
457
if (uprcase( *cur ) == 'Y') {
458
cur++;
459
*writemask |= TGSI_WRITEMASK_Y;
460
}
461
if (uprcase( *cur ) == 'Z') {
462
cur++;
463
*writemask |= TGSI_WRITEMASK_Z;
464
}
465
if (uprcase( *cur ) == 'W') {
466
cur++;
467
*writemask |= TGSI_WRITEMASK_W;
468
}
469
470
if (*writemask == TGSI_WRITEMASK_NONE) {
471
report_error( ctx, "Writemask expected" );
472
return FALSE;
473
}
474
475
ctx->cur = cur;
476
}
477
else {
478
*writemask = TGSI_WRITEMASK_XYZW;
479
}
480
return TRUE;
481
}
482
483
484
/* <register_file_bracket> ::= <file> `['
485
*/
486
static boolean
487
parse_register_file_bracket(
488
struct translate_ctx *ctx,
489
uint *file )
490
{
491
if (!parse_file( &ctx->cur, file )) {
492
report_error( ctx, "Unknown register file" );
493
return FALSE;
494
}
495
eat_opt_white( &ctx->cur );
496
if (*ctx->cur != '[') {
497
report_error( ctx, "Expected `['" );
498
return FALSE;
499
}
500
ctx->cur++;
501
return TRUE;
502
}
503
504
/* <register_file_bracket_index> ::= <register_file_bracket> <uint>
505
*/
506
static boolean
507
parse_register_file_bracket_index(
508
struct translate_ctx *ctx,
509
uint *file,
510
int *index )
511
{
512
uint uindex;
513
514
if (!parse_register_file_bracket( ctx, file ))
515
return FALSE;
516
eat_opt_white( &ctx->cur );
517
if (!parse_uint( &ctx->cur, &uindex )) {
518
report_error( ctx, "Expected literal unsigned integer" );
519
return FALSE;
520
}
521
*index = (int) uindex;
522
return TRUE;
523
}
524
525
/* Parse simple 1d register operand.
526
* <register_dst> ::= <register_file_bracket_index> `]'
527
*/
528
static boolean
529
parse_register_1d(struct translate_ctx *ctx,
530
uint *file,
531
int *index )
532
{
533
if (!parse_register_file_bracket_index( ctx, file, index ))
534
return FALSE;
535
eat_opt_white( &ctx->cur );
536
if (*ctx->cur != ']') {
537
report_error( ctx, "Expected `]'" );
538
return FALSE;
539
}
540
ctx->cur++;
541
return TRUE;
542
}
543
544
struct parsed_bracket {
545
int index;
546
547
uint ind_file;
548
int ind_index;
549
uint ind_comp;
550
uint ind_array;
551
};
552
553
554
static boolean
555
parse_register_bracket(
556
struct translate_ctx *ctx,
557
struct parsed_bracket *brackets)
558
{
559
const char *cur;
560
uint uindex;
561
562
memset(brackets, 0, sizeof(struct parsed_bracket));
563
564
eat_opt_white( &ctx->cur );
565
566
cur = ctx->cur;
567
if (parse_file( &cur, &brackets->ind_file )) {
568
if (!parse_register_1d( ctx, &brackets->ind_file,
569
&brackets->ind_index ))
570
return FALSE;
571
eat_opt_white( &ctx->cur );
572
573
if (*ctx->cur == '.') {
574
ctx->cur++;
575
eat_opt_white(&ctx->cur);
576
577
switch (uprcase(*ctx->cur)) {
578
case 'X':
579
brackets->ind_comp = TGSI_SWIZZLE_X;
580
break;
581
case 'Y':
582
brackets->ind_comp = TGSI_SWIZZLE_Y;
583
break;
584
case 'Z':
585
brackets->ind_comp = TGSI_SWIZZLE_Z;
586
break;
587
case 'W':
588
brackets->ind_comp = TGSI_SWIZZLE_W;
589
break;
590
default:
591
report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
592
return FALSE;
593
}
594
ctx->cur++;
595
eat_opt_white(&ctx->cur);
596
}
597
598
if (*ctx->cur == '+' || *ctx->cur == '-')
599
parse_int( &ctx->cur, &brackets->index );
600
else
601
brackets->index = 0;
602
}
603
else {
604
if (!parse_uint( &ctx->cur, &uindex )) {
605
report_error( ctx, "Expected literal unsigned integer" );
606
return FALSE;
607
}
608
brackets->index = (int) uindex;
609
brackets->ind_file = TGSI_FILE_NULL;
610
brackets->ind_index = 0;
611
}
612
eat_opt_white( &ctx->cur );
613
if (*ctx->cur != ']') {
614
report_error( ctx, "Expected `]'" );
615
return FALSE;
616
}
617
ctx->cur++;
618
if (*ctx->cur == '(') {
619
ctx->cur++;
620
eat_opt_white( &ctx->cur );
621
if (!parse_uint( &ctx->cur, &brackets->ind_array )) {
622
report_error( ctx, "Expected literal unsigned integer" );
623
return FALSE;
624
}
625
eat_opt_white( &ctx->cur );
626
if (*ctx->cur != ')') {
627
report_error( ctx, "Expected `)'" );
628
return FALSE;
629
}
630
ctx->cur++;
631
}
632
return TRUE;
633
}
634
635
static boolean
636
parse_opt_register_src_bracket(
637
struct translate_ctx *ctx,
638
struct parsed_bracket *brackets,
639
int *parsed_brackets)
640
{
641
const char *cur = ctx->cur;
642
643
*parsed_brackets = 0;
644
645
eat_opt_white( &cur );
646
if (cur[0] == '[') {
647
++cur;
648
ctx->cur = cur;
649
650
if (!parse_register_bracket(ctx, brackets))
651
return FALSE;
652
653
*parsed_brackets = 1;
654
}
655
656
return TRUE;
657
}
658
659
660
/* Parse source register operand.
661
* <register_src> ::= <register_file_bracket_index> `]' |
662
* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
663
* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
664
* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
665
*/
666
static boolean
667
parse_register_src(
668
struct translate_ctx *ctx,
669
uint *file,
670
struct parsed_bracket *brackets)
671
{
672
brackets->ind_comp = TGSI_SWIZZLE_X;
673
if (!parse_register_file_bracket( ctx, file ))
674
return FALSE;
675
if (!parse_register_bracket( ctx, brackets ))
676
return FALSE;
677
678
return TRUE;
679
}
680
681
struct parsed_dcl_bracket {
682
uint first;
683
uint last;
684
};
685
686
static boolean
687
parse_register_dcl_bracket(
688
struct translate_ctx *ctx,
689
struct parsed_dcl_bracket *bracket)
690
{
691
uint uindex;
692
memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
693
694
eat_opt_white( &ctx->cur );
695
696
if (!parse_uint( &ctx->cur, &uindex )) {
697
/* it can be an empty bracket [] which means its range
698
* is from 0 to some implied size */
699
if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
700
bracket->first = 0;
701
bracket->last = ctx->implied_array_size - 1;
702
goto cleanup;
703
}
704
report_error( ctx, "Expected literal unsigned integer" );
705
return FALSE;
706
}
707
bracket->first = uindex;
708
709
eat_opt_white( &ctx->cur );
710
711
if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
712
uint uindex;
713
714
ctx->cur += 2;
715
eat_opt_white( &ctx->cur );
716
if (!parse_uint( &ctx->cur, &uindex )) {
717
report_error( ctx, "Expected literal integer" );
718
return FALSE;
719
}
720
bracket->last = (int) uindex;
721
eat_opt_white( &ctx->cur );
722
}
723
else {
724
bracket->last = bracket->first;
725
}
726
727
cleanup:
728
if (*ctx->cur != ']') {
729
report_error( ctx, "Expected `]' or `..'" );
730
return FALSE;
731
}
732
ctx->cur++;
733
return TRUE;
734
}
735
736
/* Parse register declaration.
737
* <register_dcl> ::= <register_file_bracket_index> `]' |
738
* <register_file_bracket_index> `..' <index> `]'
739
*/
740
static boolean
741
parse_register_dcl(
742
struct translate_ctx *ctx,
743
uint *file,
744
struct parsed_dcl_bracket *brackets,
745
int *num_brackets)
746
{
747
const char *cur;
748
749
*num_brackets = 0;
750
751
if (!parse_register_file_bracket( ctx, file ))
752
return FALSE;
753
if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
754
return FALSE;
755
756
*num_brackets = 1;
757
758
cur = ctx->cur;
759
eat_opt_white( &cur );
760
761
if (cur[0] == '[') {
762
bool is_in = *file == TGSI_FILE_INPUT;
763
bool is_out = *file == TGSI_FILE_OUTPUT;
764
765
++cur;
766
ctx->cur = cur;
767
if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
768
return FALSE;
769
/* for geometry shader we don't really care about
770
* the first brackets it's always the size of the
771
* input primitive. so we want to declare just
772
* the index relevant to the semantics which is in
773
* the second bracket */
774
775
/* tessellation has similar constraints to geometry shader */
776
if ((ctx->processor == PIPE_SHADER_GEOMETRY && is_in) ||
777
(ctx->processor == PIPE_SHADER_TESS_EVAL && is_in) ||
778
(ctx->processor == PIPE_SHADER_TESS_CTRL && (is_in || is_out))) {
779
brackets[0] = brackets[1];
780
*num_brackets = 1;
781
} else {
782
*num_brackets = 2;
783
}
784
}
785
786
return TRUE;
787
}
788
789
790
/* Parse destination register operand.*/
791
static boolean
792
parse_register_dst(
793
struct translate_ctx *ctx,
794
uint *file,
795
struct parsed_bracket *brackets)
796
{
797
brackets->ind_comp = TGSI_SWIZZLE_X;
798
if (!parse_register_file_bracket( ctx, file ))
799
return FALSE;
800
if (!parse_register_bracket( ctx, brackets ))
801
return FALSE;
802
803
return TRUE;
804
}
805
806
static boolean
807
parse_dst_operand(
808
struct translate_ctx *ctx,
809
struct tgsi_full_dst_register *dst )
810
{
811
uint file;
812
uint writemask;
813
const char *cur;
814
struct parsed_bracket bracket[2];
815
int parsed_opt_brackets;
816
817
if (!parse_register_dst( ctx, &file, &bracket[0] ))
818
return FALSE;
819
if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
820
return FALSE;
821
822
cur = ctx->cur;
823
eat_opt_white( &cur );
824
825
if (!parse_opt_writemask( ctx, &writemask ))
826
return FALSE;
827
828
dst->Register.File = file;
829
if (parsed_opt_brackets) {
830
dst->Register.Dimension = 1;
831
dst->Dimension.Indirect = 0;
832
dst->Dimension.Dimension = 0;
833
dst->Dimension.Index = bracket[0].index;
834
835
if (bracket[0].ind_file != TGSI_FILE_NULL) {
836
dst->Dimension.Indirect = 1;
837
dst->DimIndirect.File = bracket[0].ind_file;
838
dst->DimIndirect.Index = bracket[0].ind_index;
839
dst->DimIndirect.Swizzle = bracket[0].ind_comp;
840
dst->DimIndirect.ArrayID = bracket[0].ind_array;
841
}
842
bracket[0] = bracket[1];
843
}
844
dst->Register.Index = bracket[0].index;
845
dst->Register.WriteMask = writemask;
846
if (bracket[0].ind_file != TGSI_FILE_NULL) {
847
dst->Register.Indirect = 1;
848
dst->Indirect.File = bracket[0].ind_file;
849
dst->Indirect.Index = bracket[0].ind_index;
850
dst->Indirect.Swizzle = bracket[0].ind_comp;
851
dst->Indirect.ArrayID = bracket[0].ind_array;
852
}
853
return TRUE;
854
}
855
856
static boolean
857
parse_optional_swizzle(
858
struct translate_ctx *ctx,
859
uint *swizzle,
860
boolean *parsed_swizzle,
861
int components)
862
{
863
const char *cur = ctx->cur;
864
865
*parsed_swizzle = FALSE;
866
867
eat_opt_white( &cur );
868
if (*cur == '.') {
869
int i;
870
871
cur++;
872
eat_opt_white( &cur );
873
for (i = 0; i < components; i++) {
874
if (uprcase( *cur ) == 'X')
875
swizzle[i] = TGSI_SWIZZLE_X;
876
else if (uprcase( *cur ) == 'Y')
877
swizzle[i] = TGSI_SWIZZLE_Y;
878
else if (uprcase( *cur ) == 'Z')
879
swizzle[i] = TGSI_SWIZZLE_Z;
880
else if (uprcase( *cur ) == 'W')
881
swizzle[i] = TGSI_SWIZZLE_W;
882
else {
883
report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
884
return FALSE;
885
}
886
cur++;
887
}
888
*parsed_swizzle = TRUE;
889
ctx->cur = cur;
890
}
891
return TRUE;
892
}
893
894
static boolean
895
parse_src_operand(
896
struct translate_ctx *ctx,
897
struct tgsi_full_src_register *src )
898
{
899
uint file;
900
uint swizzle[4];
901
boolean parsed_swizzle;
902
struct parsed_bracket bracket[2];
903
int parsed_opt_brackets;
904
905
if (*ctx->cur == '-') {
906
ctx->cur++;
907
eat_opt_white( &ctx->cur );
908
src->Register.Negate = 1;
909
}
910
911
if (*ctx->cur == '|') {
912
ctx->cur++;
913
eat_opt_white( &ctx->cur );
914
src->Register.Absolute = 1;
915
}
916
917
if (!parse_register_src(ctx, &file, &bracket[0]))
918
return FALSE;
919
if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
920
return FALSE;
921
922
src->Register.File = file;
923
if (parsed_opt_brackets) {
924
src->Register.Dimension = 1;
925
src->Dimension.Indirect = 0;
926
src->Dimension.Dimension = 0;
927
src->Dimension.Index = bracket[0].index;
928
if (bracket[0].ind_file != TGSI_FILE_NULL) {
929
src->Dimension.Indirect = 1;
930
src->DimIndirect.File = bracket[0].ind_file;
931
src->DimIndirect.Index = bracket[0].ind_index;
932
src->DimIndirect.Swizzle = bracket[0].ind_comp;
933
src->DimIndirect.ArrayID = bracket[0].ind_array;
934
}
935
bracket[0] = bracket[1];
936
}
937
src->Register.Index = bracket[0].index;
938
if (bracket[0].ind_file != TGSI_FILE_NULL) {
939
src->Register.Indirect = 1;
940
src->Indirect.File = bracket[0].ind_file;
941
src->Indirect.Index = bracket[0].ind_index;
942
src->Indirect.Swizzle = bracket[0].ind_comp;
943
src->Indirect.ArrayID = bracket[0].ind_array;
944
}
945
946
/* Parse optional swizzle.
947
*/
948
if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) {
949
if (parsed_swizzle) {
950
src->Register.SwizzleX = swizzle[0];
951
src->Register.SwizzleY = swizzle[1];
952
src->Register.SwizzleZ = swizzle[2];
953
src->Register.SwizzleW = swizzle[3];
954
}
955
}
956
957
if (src->Register.Absolute) {
958
eat_opt_white( &ctx->cur );
959
if (*ctx->cur != '|') {
960
report_error( ctx, "Expected `|'" );
961
return FALSE;
962
}
963
ctx->cur++;
964
}
965
966
967
return TRUE;
968
}
969
970
static boolean
971
parse_texoffset_operand(
972
struct translate_ctx *ctx,
973
struct tgsi_texture_offset *src )
974
{
975
uint file;
976
uint swizzle[3];
977
boolean parsed_swizzle;
978
struct parsed_bracket bracket;
979
980
if (!parse_register_src(ctx, &file, &bracket))
981
return FALSE;
982
983
src->File = file;
984
src->Index = bracket.index;
985
986
/* Parse optional swizzle.
987
*/
988
if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) {
989
if (parsed_swizzle) {
990
src->SwizzleX = swizzle[0];
991
src->SwizzleY = swizzle[1];
992
src->SwizzleZ = swizzle[2];
993
}
994
}
995
996
return TRUE;
997
}
998
999
static boolean
1000
match_inst(const char **pcur,
1001
unsigned *saturate,
1002
unsigned *precise,
1003
const struct tgsi_opcode_info *info)
1004
{
1005
const char *cur = *pcur;
1006
const char *mnemonic = tgsi_get_opcode_name(info->opcode);
1007
1008
/* simple case: the whole string matches the instruction name */
1009
if (str_match_nocase_whole(&cur, mnemonic)) {
1010
*pcur = cur;
1011
*saturate = 0;
1012
*precise = 0;
1013
return TRUE;
1014
}
1015
1016
if (str_match_no_case(&cur, mnemonic)) {
1017
/* the instruction has a suffix, figure it out */
1018
if (str_match_no_case(&cur, "_SAT")) {
1019
*pcur = cur;
1020
*saturate = 1;
1021
}
1022
1023
if (str_match_no_case(&cur, "_PRECISE")) {
1024
*pcur = cur;
1025
*precise = 1;
1026
}
1027
1028
if (!is_digit_alpha_underscore(cur))
1029
return TRUE;
1030
}
1031
1032
return FALSE;
1033
}
1034
1035
static boolean
1036
parse_instruction(
1037
struct translate_ctx *ctx,
1038
boolean has_label )
1039
{
1040
int i;
1041
uint saturate = 0;
1042
uint precise = 0;
1043
const struct tgsi_opcode_info *info;
1044
struct tgsi_full_instruction inst;
1045
const char *cur;
1046
uint advance;
1047
1048
inst = tgsi_default_full_instruction();
1049
1050
/* Parse instruction name.
1051
*/
1052
eat_opt_white( &ctx->cur );
1053
for (i = 0; i < TGSI_OPCODE_LAST; i++) {
1054
cur = ctx->cur;
1055
1056
info = tgsi_get_opcode_info( i );
1057
if (match_inst(&cur, &saturate, &precise, info)) {
1058
if (info->num_dst + info->num_src + info->is_tex == 0) {
1059
ctx->cur = cur;
1060
break;
1061
}
1062
else if (*cur == '\0' || eat_white( &cur )) {
1063
ctx->cur = cur;
1064
break;
1065
}
1066
}
1067
}
1068
if (i == TGSI_OPCODE_LAST) {
1069
if (has_label)
1070
report_error( ctx, "Unknown opcode" );
1071
else
1072
report_error( ctx, "Expected `DCL', `IMM' or a label" );
1073
return FALSE;
1074
}
1075
1076
inst.Instruction.Opcode = i;
1077
inst.Instruction.Saturate = saturate;
1078
inst.Instruction.Precise = precise;
1079
inst.Instruction.NumDstRegs = info->num_dst;
1080
inst.Instruction.NumSrcRegs = info->num_src;
1081
1082
if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
1083
/*
1084
* These are not considered tex opcodes here (no additional
1085
* target argument) however we're required to set the Texture
1086
* bit so we can set the number of tex offsets.
1087
*/
1088
inst.Instruction.Texture = 1;
1089
inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
1090
}
1091
1092
if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) ||
1093
i == TGSI_OPCODE_RESQ) {
1094
inst.Instruction.Memory = 1;
1095
inst.Memory.Qualifier = 0;
1096
}
1097
1098
assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS);
1099
assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS);
1100
1101
/* Parse instruction operands.
1102
*/
1103
for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
1104
if (i > 0) {
1105
eat_opt_white( &ctx->cur );
1106
if (*ctx->cur != ',') {
1107
report_error( ctx, "Expected `,'" );
1108
return FALSE;
1109
}
1110
ctx->cur++;
1111
eat_opt_white( &ctx->cur );
1112
}
1113
1114
if (i < info->num_dst) {
1115
if (!parse_dst_operand( ctx, &inst.Dst[i] ))
1116
return FALSE;
1117
}
1118
else if (i < info->num_dst + info->num_src) {
1119
if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
1120
return FALSE;
1121
}
1122
else {
1123
uint j;
1124
1125
for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
1126
if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
1127
inst.Instruction.Texture = 1;
1128
inst.Texture.Texture = j;
1129
break;
1130
}
1131
}
1132
if (j == TGSI_TEXTURE_COUNT) {
1133
report_error( ctx, "Expected texture target" );
1134
return FALSE;
1135
}
1136
}
1137
}
1138
1139
cur = ctx->cur;
1140
eat_opt_white( &cur );
1141
for (i = 0; inst.Instruction.Texture && *cur == ',' && i < TGSI_FULL_MAX_TEX_OFFSETS; i++) {
1142
cur++;
1143
eat_opt_white( &cur );
1144
ctx->cur = cur;
1145
if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] ))
1146
return FALSE;
1147
cur = ctx->cur;
1148
eat_opt_white( &cur );
1149
}
1150
inst.Texture.NumOffsets = i;
1151
1152
cur = ctx->cur;
1153
eat_opt_white(&cur);
1154
1155
for (; inst.Instruction.Memory && *cur == ',';
1156
ctx->cur = cur, eat_opt_white(&cur)) {
1157
int j;
1158
1159
cur++;
1160
eat_opt_white(&cur);
1161
1162
j = str_match_name_from_array(&cur, tgsi_memory_names,
1163
ARRAY_SIZE(tgsi_memory_names));
1164
if (j >= 0) {
1165
inst.Memory.Qualifier |= 1U << j;
1166
continue;
1167
}
1168
1169
j = str_match_name_from_array(&cur, tgsi_texture_names,
1170
ARRAY_SIZE(tgsi_texture_names));
1171
if (j >= 0) {
1172
inst.Memory.Texture = j;
1173
continue;
1174
}
1175
1176
j = str_match_format(&cur);
1177
if (j >= 0) {
1178
inst.Memory.Format = j;
1179
continue;
1180
}
1181
1182
ctx->cur = cur;
1183
report_error(ctx, "Expected memory qualifier, texture target, or format\n");
1184
return FALSE;
1185
}
1186
1187
cur = ctx->cur;
1188
eat_opt_white( &cur );
1189
if (info->is_branch && *cur == ':') {
1190
uint target;
1191
1192
cur++;
1193
eat_opt_white( &cur );
1194
if (!parse_uint( &cur, &target )) {
1195
report_error( ctx, "Expected a label" );
1196
return FALSE;
1197
}
1198
inst.Instruction.Label = 1;
1199
inst.Label.Label = target;
1200
ctx->cur = cur;
1201
}
1202
1203
advance = tgsi_build_full_instruction(
1204
&inst,
1205
ctx->tokens_cur,
1206
ctx->header,
1207
(uint) (ctx->tokens_end - ctx->tokens_cur) );
1208
if (advance == 0)
1209
return FALSE;
1210
ctx->tokens_cur += advance;
1211
1212
return TRUE;
1213
}
1214
1215
/* parses a 4-touple of the form {x, y, z, w}
1216
* where x, y, z, w are numbers */
1217
static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
1218
union tgsi_immediate_data *values)
1219
{
1220
unsigned i;
1221
int ret;
1222
1223
eat_opt_white( &ctx->cur );
1224
if (*ctx->cur != '{') {
1225
report_error( ctx, "Expected `{'" );
1226
return FALSE;
1227
}
1228
ctx->cur++;
1229
for (i = 0; i < 4; i++) {
1230
eat_opt_white( &ctx->cur );
1231
if (i > 0) {
1232
if (*ctx->cur != ',') {
1233
report_error( ctx, "Expected `,'" );
1234
return FALSE;
1235
}
1236
ctx->cur++;
1237
eat_opt_white( &ctx->cur );
1238
}
1239
1240
switch (type) {
1241
case TGSI_IMM_FLOAT64:
1242
ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
1243
i++;
1244
break;
1245
case TGSI_IMM_INT64:
1246
ret = parse_int64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
1247
i++;
1248
break;
1249
case TGSI_IMM_UINT64:
1250
ret = parse_uint64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
1251
i++;
1252
break;
1253
case TGSI_IMM_FLOAT32:
1254
ret = parse_float(&ctx->cur, &values[i].Float);
1255
break;
1256
case TGSI_IMM_UINT32:
1257
ret = parse_uint(&ctx->cur, &values[i].Uint);
1258
break;
1259
case TGSI_IMM_INT32:
1260
ret = parse_int(&ctx->cur, &values[i].Int);
1261
break;
1262
default:
1263
assert(0);
1264
ret = FALSE;
1265
break;
1266
}
1267
1268
if (!ret) {
1269
report_error( ctx, "Expected immediate constant" );
1270
return FALSE;
1271
}
1272
}
1273
eat_opt_white( &ctx->cur );
1274
if (*ctx->cur != '}') {
1275
report_error( ctx, "Expected `}'" );
1276
return FALSE;
1277
}
1278
ctx->cur++;
1279
1280
return TRUE;
1281
}
1282
1283
static boolean parse_declaration( struct translate_ctx *ctx )
1284
{
1285
struct tgsi_full_declaration decl;
1286
uint file;
1287
struct parsed_dcl_bracket brackets[2];
1288
int num_brackets;
1289
uint writemask;
1290
const char *cur, *cur2;
1291
uint advance;
1292
boolean is_vs_input;
1293
1294
if (!eat_white( &ctx->cur )) {
1295
report_error( ctx, "Syntax error" );
1296
return FALSE;
1297
}
1298
if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1299
return FALSE;
1300
if (!parse_opt_writemask( ctx, &writemask ))
1301
return FALSE;
1302
1303
decl = tgsi_default_full_declaration();
1304
decl.Declaration.File = file;
1305
decl.Declaration.UsageMask = writemask;
1306
1307
if (num_brackets == 1) {
1308
decl.Range.First = brackets[0].first;
1309
decl.Range.Last = brackets[0].last;
1310
} else {
1311
decl.Range.First = brackets[1].first;
1312
decl.Range.Last = brackets[1].last;
1313
1314
decl.Declaration.Dimension = 1;
1315
decl.Dim.Index2D = brackets[0].first;
1316
}
1317
1318
is_vs_input = (file == TGSI_FILE_INPUT &&
1319
ctx->processor == PIPE_SHADER_VERTEX);
1320
1321
cur = ctx->cur;
1322
eat_opt_white( &cur );
1323
if (*cur == ',') {
1324
cur2 = cur;
1325
cur2++;
1326
eat_opt_white( &cur2 );
1327
if (str_match_nocase_whole( &cur2, "ARRAY" )) {
1328
int arrayid;
1329
if (*cur2 != '(') {
1330
report_error( ctx, "Expected `('" );
1331
return FALSE;
1332
}
1333
cur2++;
1334
eat_opt_white( &cur2 );
1335
if (!parse_int( &cur2, &arrayid )) {
1336
report_error( ctx, "Expected `,'" );
1337
return FALSE;
1338
}
1339
eat_opt_white( &cur2 );
1340
if (*cur2 != ')') {
1341
report_error( ctx, "Expected `)'" );
1342
return FALSE;
1343
}
1344
cur2++;
1345
decl.Declaration.Array = 1;
1346
decl.Array.ArrayID = arrayid;
1347
ctx->cur = cur = cur2;
1348
}
1349
}
1350
1351
if (*cur == ',' && !is_vs_input) {
1352
uint i, j;
1353
1354
cur++;
1355
eat_opt_white( &cur );
1356
if (file == TGSI_FILE_IMAGE) {
1357
for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1358
if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1359
decl.Image.Resource = i;
1360
break;
1361
}
1362
}
1363
if (i == TGSI_TEXTURE_COUNT) {
1364
report_error(ctx, "Expected texture target");
1365
return FALSE;
1366
}
1367
1368
cur2 = cur;
1369
eat_opt_white(&cur2);
1370
while (*cur2 == ',') {
1371
cur2++;
1372
eat_opt_white(&cur2);
1373
if (str_match_nocase_whole(&cur2, "RAW")) {
1374
decl.Image.Raw = 1;
1375
1376
} else if (str_match_nocase_whole(&cur2, "WR")) {
1377
decl.Image.Writable = 1;
1378
1379
} else {
1380
int format = str_match_format(&cur2);
1381
if (format < 0)
1382
break;
1383
1384
decl.Image.Format = format;
1385
}
1386
cur = cur2;
1387
eat_opt_white(&cur2);
1388
}
1389
1390
ctx->cur = cur;
1391
1392
} else if (file == TGSI_FILE_SAMPLER_VIEW) {
1393
for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1394
if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1395
decl.SamplerView.Resource = i;
1396
break;
1397
}
1398
}
1399
if (i == TGSI_TEXTURE_COUNT) {
1400
report_error(ctx, "Expected texture target");
1401
return FALSE;
1402
}
1403
eat_opt_white( &cur );
1404
if (*cur != ',') {
1405
report_error( ctx, "Expected `,'" );
1406
return FALSE;
1407
}
1408
++cur;
1409
eat_opt_white( &cur );
1410
for (j = 0; j < 4; ++j) {
1411
for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) {
1412
if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) {
1413
switch (j) {
1414
case 0:
1415
decl.SamplerView.ReturnTypeX = i;
1416
break;
1417
case 1:
1418
decl.SamplerView.ReturnTypeY = i;
1419
break;
1420
case 2:
1421
decl.SamplerView.ReturnTypeZ = i;
1422
break;
1423
case 3:
1424
decl.SamplerView.ReturnTypeW = i;
1425
break;
1426
default:
1427
assert(0);
1428
}
1429
break;
1430
}
1431
}
1432
if (i == TGSI_RETURN_TYPE_COUNT) {
1433
if (j == 0 || j > 2) {
1434
report_error(ctx, "Expected type name");
1435
return FALSE;
1436
}
1437
break;
1438
} else {
1439
cur2 = cur;
1440
eat_opt_white( &cur2 );
1441
if (*cur2 == ',') {
1442
cur2++;
1443
eat_opt_white( &cur2 );
1444
cur = cur2;
1445
continue;
1446
} else
1447
break;
1448
}
1449
}
1450
if (j < 4) {
1451
decl.SamplerView.ReturnTypeY =
1452
decl.SamplerView.ReturnTypeZ =
1453
decl.SamplerView.ReturnTypeW =
1454
decl.SamplerView.ReturnTypeX;
1455
}
1456
ctx->cur = cur;
1457
} else if (file == TGSI_FILE_BUFFER) {
1458
if (str_match_nocase_whole(&cur, "ATOMIC")) {
1459
decl.Declaration.Atomic = 1;
1460
ctx->cur = cur;
1461
}
1462
} else if (file == TGSI_FILE_MEMORY) {
1463
if (str_match_nocase_whole(&cur, "GLOBAL")) {
1464
/* Note this is a no-op global is the default */
1465
decl.Declaration.MemType = TGSI_MEMORY_TYPE_GLOBAL;
1466
ctx->cur = cur;
1467
} else if (str_match_nocase_whole(&cur, "SHARED")) {
1468
decl.Declaration.MemType = TGSI_MEMORY_TYPE_SHARED;
1469
ctx->cur = cur;
1470
} else if (str_match_nocase_whole(&cur, "PRIVATE")) {
1471
decl.Declaration.MemType = TGSI_MEMORY_TYPE_PRIVATE;
1472
ctx->cur = cur;
1473
} else if (str_match_nocase_whole(&cur, "INPUT")) {
1474
decl.Declaration.MemType = TGSI_MEMORY_TYPE_INPUT;
1475
ctx->cur = cur;
1476
}
1477
} else {
1478
if (str_match_nocase_whole(&cur, "LOCAL")) {
1479
decl.Declaration.Local = 1;
1480
ctx->cur = cur;
1481
}
1482
1483
cur = ctx->cur;
1484
eat_opt_white( &cur );
1485
if (*cur == ',') {
1486
cur++;
1487
eat_opt_white( &cur );
1488
1489
for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1490
if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
1491
uint index;
1492
1493
cur2 = cur;
1494
eat_opt_white( &cur2 );
1495
if (*cur2 == '[') {
1496
cur2++;
1497
eat_opt_white( &cur2 );
1498
if (!parse_uint( &cur2, &index )) {
1499
report_error( ctx, "Expected literal integer" );
1500
return FALSE;
1501
}
1502
eat_opt_white( &cur2 );
1503
if (*cur2 != ']') {
1504
report_error( ctx, "Expected `]'" );
1505
return FALSE;
1506
}
1507
cur2++;
1508
1509
decl.Semantic.Index = index;
1510
1511
cur = cur2;
1512
}
1513
1514
decl.Declaration.Semantic = 1;
1515
decl.Semantic.Name = i;
1516
1517
ctx->cur = cur;
1518
break;
1519
}
1520
}
1521
}
1522
}
1523
}
1524
1525
cur = ctx->cur;
1526
eat_opt_white( &cur );
1527
if (*cur == ',' &&
1528
file == TGSI_FILE_OUTPUT && ctx->processor == PIPE_SHADER_GEOMETRY) {
1529
cur++;
1530
eat_opt_white(&cur);
1531
if (str_match_nocase_whole(&cur, "STREAM")) {
1532
uint stream[4];
1533
1534
eat_opt_white(&cur);
1535
if (*cur != '(') {
1536
report_error(ctx, "Expected '('");
1537
return FALSE;
1538
}
1539
cur++;
1540
1541
for (int i = 0; i < 4; ++i) {
1542
eat_opt_white(&cur);
1543
if (!parse_uint(&cur, &stream[i])) {
1544
report_error(ctx, "Expected literal integer");
1545
return FALSE;
1546
}
1547
1548
eat_opt_white(&cur);
1549
if (i < 3) {
1550
if (*cur != ',') {
1551
report_error(ctx, "Expected ','");
1552
return FALSE;
1553
}
1554
cur++;
1555
}
1556
}
1557
1558
if (*cur != ')') {
1559
report_error(ctx, "Expected ')'");
1560
return FALSE;
1561
}
1562
cur++;
1563
1564
decl.Semantic.StreamX = stream[0];
1565
decl.Semantic.StreamY = stream[1];
1566
decl.Semantic.StreamZ = stream[2];
1567
decl.Semantic.StreamW = stream[3];
1568
1569
ctx->cur = cur;
1570
}
1571
}
1572
1573
cur = ctx->cur;
1574
eat_opt_white( &cur );
1575
if (*cur == ',' && !is_vs_input) {
1576
uint i;
1577
1578
cur++;
1579
eat_opt_white( &cur );
1580
for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1581
if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
1582
decl.Declaration.Interpolate = 1;
1583
decl.Interp.Interpolate = i;
1584
1585
ctx->cur = cur;
1586
break;
1587
}
1588
}
1589
}
1590
1591
cur = ctx->cur;
1592
eat_opt_white( &cur );
1593
if (*cur == ',' && !is_vs_input) {
1594
uint i;
1595
1596
cur++;
1597
eat_opt_white( &cur );
1598
for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) {
1599
if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) {
1600
decl.Interp.Location = i;
1601
1602
ctx->cur = cur;
1603
break;
1604
}
1605
}
1606
}
1607
1608
cur = ctx->cur;
1609
eat_opt_white( &cur );
1610
if (*cur == ',' && !is_vs_input) {
1611
cur++;
1612
eat_opt_white( &cur );
1613
if (str_match_nocase_whole( &cur, tgsi_invariant_name )) {
1614
decl.Declaration.Invariant = 1;
1615
ctx->cur = cur;
1616
} else {
1617
report_error( ctx, "Expected semantic, interpolate attribute, or invariant ");
1618
return FALSE;
1619
}
1620
}
1621
1622
advance = tgsi_build_full_declaration(
1623
&decl,
1624
ctx->tokens_cur,
1625
ctx->header,
1626
(uint) (ctx->tokens_end - ctx->tokens_cur) );
1627
1628
if (advance == 0)
1629
return FALSE;
1630
ctx->tokens_cur += advance;
1631
1632
return TRUE;
1633
}
1634
1635
static boolean parse_immediate( struct translate_ctx *ctx )
1636
{
1637
struct tgsi_full_immediate imm;
1638
uint advance;
1639
uint type;
1640
1641
if (*ctx->cur == '[') {
1642
uint uindex;
1643
1644
++ctx->cur;
1645
1646
eat_opt_white( &ctx->cur );
1647
if (!parse_uint( &ctx->cur, &uindex )) {
1648
report_error( ctx, "Expected literal unsigned integer" );
1649
return FALSE;
1650
}
1651
1652
if (uindex != ctx->num_immediates) {
1653
report_error( ctx, "Immediates must be sorted" );
1654
return FALSE;
1655
}
1656
1657
eat_opt_white( &ctx->cur );
1658
if (*ctx->cur != ']') {
1659
report_error( ctx, "Expected `]'" );
1660
return FALSE;
1661
}
1662
1663
ctx->cur++;
1664
}
1665
1666
if (!eat_white( &ctx->cur )) {
1667
report_error( ctx, "Syntax error" );
1668
return FALSE;
1669
}
1670
for (type = 0; type < ARRAY_SIZE(tgsi_immediate_type_names); ++type) {
1671
if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
1672
break;
1673
}
1674
if (type == ARRAY_SIZE(tgsi_immediate_type_names)) {
1675
report_error( ctx, "Expected immediate type" );
1676
return FALSE;
1677
}
1678
1679
imm = tgsi_default_full_immediate();
1680
imm.Immediate.NrTokens += 4;
1681
imm.Immediate.DataType = type;
1682
parse_immediate_data(ctx, type, imm.u);
1683
1684
advance = tgsi_build_full_immediate(
1685
&imm,
1686
ctx->tokens_cur,
1687
ctx->header,
1688
(uint) (ctx->tokens_end - ctx->tokens_cur) );
1689
if (advance == 0)
1690
return FALSE;
1691
ctx->tokens_cur += advance;
1692
1693
ctx->num_immediates++;
1694
1695
return TRUE;
1696
}
1697
1698
static boolean
1699
parse_primitive( const char **pcur, uint *primitive )
1700
{
1701
uint i;
1702
1703
for (i = 0; i < PIPE_PRIM_MAX; i++) {
1704
const char *cur = *pcur;
1705
1706
if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
1707
*primitive = i;
1708
*pcur = cur;
1709
return TRUE;
1710
}
1711
}
1712
return FALSE;
1713
}
1714
1715
static boolean
1716
parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1717
{
1718
uint i;
1719
1720
for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_origin_names); i++) {
1721
const char *cur = *pcur;
1722
1723
if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
1724
*fs_coord_origin = i;
1725
*pcur = cur;
1726
return TRUE;
1727
}
1728
}
1729
return FALSE;
1730
}
1731
1732
static boolean
1733
parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1734
{
1735
uint i;
1736
1737
for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_pixel_center_names); i++) {
1738
const char *cur = *pcur;
1739
1740
if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
1741
*fs_coord_pixel_center = i;
1742
*pcur = cur;
1743
return TRUE;
1744
}
1745
}
1746
return FALSE;
1747
}
1748
1749
static boolean
1750
parse_property_next_shader( const char **pcur, uint *next_shader )
1751
{
1752
uint i;
1753
1754
for (i = 0; i < ARRAY_SIZE(tgsi_processor_type_names); i++) {
1755
const char *cur = *pcur;
1756
1757
if (str_match_nocase_whole( &cur, tgsi_processor_type_names[i])) {
1758
*next_shader = i;
1759
*pcur = cur;
1760
return TRUE;
1761
}
1762
}
1763
return FALSE;
1764
}
1765
1766
static boolean parse_property( struct translate_ctx *ctx )
1767
{
1768
struct tgsi_full_property prop;
1769
uint property_name;
1770
uint values[8];
1771
uint advance;
1772
char id[64];
1773
1774
if (!eat_white( &ctx->cur )) {
1775
report_error( ctx, "Syntax error" );
1776
return FALSE;
1777
}
1778
if (!parse_identifier( &ctx->cur, id, sizeof(id) )) {
1779
report_error( ctx, "Syntax error" );
1780
return FALSE;
1781
}
1782
for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1783
++property_name) {
1784
if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
1785
break;
1786
}
1787
}
1788
if (property_name >= TGSI_PROPERTY_COUNT) {
1789
debug_printf( "\nError: Unknown property : '%s'", id );
1790
return FALSE;
1791
}
1792
1793
eat_opt_white( &ctx->cur );
1794
switch(property_name) {
1795
case TGSI_PROPERTY_GS_INPUT_PRIM:
1796
case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1797
if (!parse_primitive(&ctx->cur, &values[0] )) {
1798
report_error( ctx, "Unknown primitive name as property!" );
1799
return FALSE;
1800
}
1801
if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1802
ctx->processor == PIPE_SHADER_GEOMETRY) {
1803
ctx->implied_array_size = u_vertices_per_prim(values[0]);
1804
}
1805
break;
1806
case TGSI_PROPERTY_FS_COORD_ORIGIN:
1807
if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1808
report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1809
return FALSE;
1810
}
1811
break;
1812
case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1813
if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1814
report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1815
return FALSE;
1816
}
1817
break;
1818
case TGSI_PROPERTY_NEXT_SHADER:
1819
if (!parse_property_next_shader(&ctx->cur, &values[0] )) {
1820
report_error( ctx, "Unknown next shader property value." );
1821
return FALSE;
1822
}
1823
break;
1824
case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
1825
default:
1826
if (!parse_uint(&ctx->cur, &values[0] )) {
1827
report_error( ctx, "Expected unsigned integer as property!" );
1828
return FALSE;
1829
}
1830
}
1831
1832
prop = tgsi_default_full_property();
1833
prop.Property.PropertyName = property_name;
1834
prop.Property.NrTokens += 1;
1835
prop.u[0].Data = values[0];
1836
1837
advance = tgsi_build_full_property(
1838
&prop,
1839
ctx->tokens_cur,
1840
ctx->header,
1841
(uint) (ctx->tokens_end - ctx->tokens_cur) );
1842
if (advance == 0)
1843
return FALSE;
1844
ctx->tokens_cur += advance;
1845
1846
return TRUE;
1847
}
1848
1849
1850
static boolean translate( struct translate_ctx *ctx )
1851
{
1852
eat_opt_white( &ctx->cur );
1853
if (!parse_header( ctx ))
1854
return FALSE;
1855
1856
if (ctx->processor == PIPE_SHADER_TESS_CTRL ||
1857
ctx->processor == PIPE_SHADER_TESS_EVAL)
1858
ctx->implied_array_size = 32;
1859
1860
while (*ctx->cur != '\0') {
1861
uint label_val = 0;
1862
if (!eat_white( &ctx->cur )) {
1863
report_error( ctx, "Syntax error" );
1864
return FALSE;
1865
}
1866
1867
if (*ctx->cur == '\0')
1868
break;
1869
if (parse_label( ctx, &label_val )) {
1870
if (!parse_instruction( ctx, TRUE ))
1871
return FALSE;
1872
}
1873
else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
1874
if (!parse_declaration( ctx ))
1875
return FALSE;
1876
}
1877
else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
1878
if (!parse_immediate( ctx ))
1879
return FALSE;
1880
}
1881
else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
1882
if (!parse_property( ctx ))
1883
return FALSE;
1884
}
1885
else if (!parse_instruction( ctx, FALSE )) {
1886
return FALSE;
1887
}
1888
}
1889
1890
return TRUE;
1891
}
1892
1893
boolean
1894
tgsi_text_translate(
1895
const char *text,
1896
struct tgsi_token *tokens,
1897
uint num_tokens )
1898
{
1899
struct translate_ctx ctx = {0};
1900
1901
ctx.text = text;
1902
ctx.cur = text;
1903
ctx.tokens = tokens;
1904
ctx.tokens_cur = tokens;
1905
ctx.tokens_end = tokens + num_tokens;
1906
1907
if (!translate( &ctx ))
1908
return FALSE;
1909
1910
return tgsi_sanity_check( tokens );
1911
}
1912
1913