Path: blob/21.2-virgl/src/gallium/auxiliary/tgsi/tgsi_text.c
4565 views
/**************************************************************************1*2* Copyright 2008 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627#include "util/u_debug.h"28#include "util/u_memory.h"29#include "util/u_prim.h"30#include "pipe/p_defines.h"31#include "util/u_inlines.h"32#include "tgsi_text.h"33#include "tgsi_build.h"34#include "tgsi_info.h"35#include "tgsi_parse.h"36#include "tgsi_sanity.h"37#include "tgsi_strings.h"38#include "tgsi_util.h"39#include "tgsi_dump.h"4041static boolean is_alpha_underscore( const char *cur )42{43return44(*cur >= 'a' && *cur <= 'z') ||45(*cur >= 'A' && *cur <= 'Z') ||46*cur == '_';47}4849static boolean is_digit( const char *cur )50{51return *cur >= '0' && *cur <= '9';52}5354static boolean is_digit_alpha_underscore( const char *cur )55{56return is_digit( cur ) || is_alpha_underscore( cur );57}5859static char uprcase( char c )60{61if (c >= 'a' && c <= 'z')62return c + 'A' - 'a';63return c;64}6566/*67* Ignore case of str1 and assume str1 is already uppercase.68* Return TRUE iff str1 and str2 are equal.69*/70static int71streq_nocase_uprcase(const char *str1,72const char *str2)73{74while (*str1 && *str2) {75if (*str1 != uprcase(*str2))76return FALSE;77str1++;78str2++;79}80return *str1 == 0 && *str2 == 0;81}8283/* Return TRUE if both strings match.84* The second string is terminated by zero.85* The pointer to the first string is moved at end of the read word86* on success.87*/88static boolean str_match_no_case( const char **pcur, const char *str )89{90const char *cur = *pcur;9192while (*str != '\0' && *str == uprcase( *cur )) {93str++;94cur++;95}96if (*str == '\0') {97*pcur = cur;98return TRUE;99}100return FALSE;101}102103/* Return TRUE if both strings match.104* The first string is be terminated by a non-digit non-letter non-underscore105* character, the second string is terminated by zero.106* The pointer to the first string is moved at end of the read word107* on success.108*/109static boolean str_match_nocase_whole( const char **pcur, const char *str )110{111const char *cur = *pcur;112113if (str_match_no_case(&cur, str) &&114!is_digit_alpha_underscore(cur)) {115*pcur = cur;116return TRUE;117}118return FALSE;119}120121/* Return the array index that matches starting at *pcur, where the string at122* *pcur is terminated by a non-digit non-letter non-underscore.123* Returns -1 if no match is found.124*125* On success, the pointer to the first string is moved to the end of the read126* word.127*/128static int str_match_name_from_array(const char **pcur,129const char * const *array,130unsigned array_size)131{132for (unsigned j = 0; j < array_size; ++j) {133if (str_match_nocase_whole(pcur, array[j]))134return j;135}136return -1;137}138139/* Return the format corresponding to the name at *pcur.140* Returns -1 if there is no format name.141*142* On success, the pointer to the string is moved to the end of the read format143* name.144*/145static int str_match_format(const char **pcur)146{147for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) {148const struct util_format_description *desc =149util_format_description(i);150if (desc && str_match_nocase_whole(pcur, desc->name)) {151return i;152}153}154return -1;155}156157/* Eat zero or more whitespaces.158*/159static void eat_opt_white( const char **pcur )160{161while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')162(*pcur)++;163}164165/* Eat one or more whitespaces.166* Return TRUE if at least one whitespace eaten.167*/168static boolean eat_white( const char **pcur )169{170const char *cur = *pcur;171172eat_opt_white( pcur );173return *pcur > cur;174}175176/* Parse unsigned integer.177* No checks for overflow.178*/179static boolean parse_uint( const char **pcur, uint *val )180{181const char *cur = *pcur;182183if (is_digit( cur )) {184*val = *cur++ - '0';185while (is_digit( cur ))186*val = *val * 10 + *cur++ - '0';187*pcur = cur;188return TRUE;189}190return FALSE;191}192193static boolean parse_int( const char **pcur, int *val )194{195const char *cur = *pcur;196int sign = (*cur == '-' ? -1 : 1);197198if (*cur == '+' || *cur == '-')199cur++;200201if (parse_uint(&cur, (uint *)val)) {202*val *= sign;203*pcur = cur;204return TRUE;205}206207return FALSE;208}209210static boolean parse_identifier( const char **pcur, char *ret, size_t len )211{212const char *cur = *pcur;213size_t i = 0;214if (is_alpha_underscore( cur )) {215ret[i++] = *cur++;216while (is_alpha_underscore( cur ) || is_digit( cur )) {217if (i == len - 1)218return FALSE;219ret[i++] = *cur++;220}221ret[i++] = '\0';222*pcur = cur;223return TRUE;224}225return FALSE;226}227228/* Parse floating point.229*/230static boolean parse_float( const char **pcur, float *val )231{232const char *cur = *pcur;233boolean integral_part = FALSE;234boolean fractional_part = FALSE;235236if (*cur == '0' && *(cur + 1) == 'x') {237union fi fi;238fi.ui = strtoul(cur, NULL, 16);239*val = fi.f;240cur += 10;241goto out;242}243244*val = (float) atof( cur );245if (*cur == '-' || *cur == '+')246cur++;247if (is_digit( cur )) {248cur++;249integral_part = TRUE;250while (is_digit( cur ))251cur++;252}253if (*cur == '.') {254cur++;255if (is_digit( cur )) {256cur++;257fractional_part = TRUE;258while (is_digit( cur ))259cur++;260}261}262if (!integral_part && !fractional_part)263return FALSE;264if (uprcase( *cur ) == 'E') {265cur++;266if (*cur == '-' || *cur == '+')267cur++;268if (is_digit( cur )) {269cur++;270while (is_digit( cur ))271cur++;272}273else274return FALSE;275}276277out:278*pcur = cur;279return TRUE;280}281282static boolean parse_double( const char **pcur, uint32_t *val0, uint32_t *val1)283{284const char *cur = *pcur;285union {286double dval;287uint32_t uval[2];288} v;289290v.dval = strtod(cur, (char**)pcur);291if (*pcur == cur)292return FALSE;293294*val0 = v.uval[0];295*val1 = v.uval[1];296297return TRUE;298}299300static boolean parse_int64( const char **pcur, uint32_t *val0, uint32_t *val1)301{302const char *cur = *pcur;303union {304int64_t i64val;305uint32_t uval[2];306} v;307308v.i64val = strtoll(cur, (char**)pcur, 0);309if (*pcur == cur)310return FALSE;311312*val0 = v.uval[0];313*val1 = v.uval[1];314315return TRUE;316}317318static boolean parse_uint64( const char **pcur, uint32_t *val0, uint32_t *val1)319{320const char *cur = *pcur;321union {322uint64_t u64val;323uint32_t uval[2];324} v;325326v.u64val = strtoull(cur, (char**)pcur, 0);327if (*pcur == cur)328return FALSE;329330*val0 = v.uval[0];331*val1 = v.uval[1];332333return TRUE;334}335336struct translate_ctx337{338const char *text;339const char *cur;340struct tgsi_token *tokens;341struct tgsi_token *tokens_cur;342struct tgsi_token *tokens_end;343struct tgsi_header *header;344unsigned processor : 4;345unsigned implied_array_size : 6;346unsigned num_immediates;347};348349static void report_error( struct translate_ctx *ctx, const char *msg )350{351int line = 1;352int column = 1;353const char *itr = ctx->text;354355while (itr != ctx->cur) {356if (*itr == '\n') {357column = 1;358++line;359}360++column;361++itr;362}363364debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );365}366367/* Parse shader header.368* Return TRUE for one of the following headers.369* FRAG370* GEOM371* VERT372*/373static boolean parse_header( struct translate_ctx *ctx )374{375uint processor;376377if (str_match_nocase_whole( &ctx->cur, "FRAG" ))378processor = PIPE_SHADER_FRAGMENT;379else if (str_match_nocase_whole( &ctx->cur, "VERT" ))380processor = PIPE_SHADER_VERTEX;381else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))382processor = PIPE_SHADER_GEOMETRY;383else if (str_match_nocase_whole( &ctx->cur, "TESS_CTRL" ))384processor = PIPE_SHADER_TESS_CTRL;385else if (str_match_nocase_whole( &ctx->cur, "TESS_EVAL" ))386processor = PIPE_SHADER_TESS_EVAL;387else if (str_match_nocase_whole( &ctx->cur, "COMP" ))388processor = PIPE_SHADER_COMPUTE;389else {390report_error( ctx, "Unknown header" );391return FALSE;392}393394if (ctx->tokens_cur >= ctx->tokens_end)395return FALSE;396ctx->header = (struct tgsi_header *) ctx->tokens_cur++;397*ctx->header = tgsi_build_header();398399if (ctx->tokens_cur >= ctx->tokens_end)400return FALSE;401*(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );402ctx->processor = processor;403404return TRUE;405}406407static boolean parse_label( struct translate_ctx *ctx, uint *val )408{409const char *cur = ctx->cur;410411if (parse_uint( &cur, val )) {412eat_opt_white( &cur );413if (*cur == ':') {414cur++;415ctx->cur = cur;416return TRUE;417}418}419return FALSE;420}421422static boolean423parse_file( const char **pcur, uint *file )424{425uint i;426427for (i = 0; i < TGSI_FILE_COUNT; i++) {428const char *cur = *pcur;429430if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) {431*pcur = cur;432*file = i;433return TRUE;434}435}436return FALSE;437}438439static boolean440parse_opt_writemask(441struct translate_ctx *ctx,442uint *writemask )443{444const char *cur;445446cur = ctx->cur;447eat_opt_white( &cur );448if (*cur == '.') {449cur++;450*writemask = TGSI_WRITEMASK_NONE;451eat_opt_white( &cur );452if (uprcase( *cur ) == 'X') {453cur++;454*writemask |= TGSI_WRITEMASK_X;455}456if (uprcase( *cur ) == 'Y') {457cur++;458*writemask |= TGSI_WRITEMASK_Y;459}460if (uprcase( *cur ) == 'Z') {461cur++;462*writemask |= TGSI_WRITEMASK_Z;463}464if (uprcase( *cur ) == 'W') {465cur++;466*writemask |= TGSI_WRITEMASK_W;467}468469if (*writemask == TGSI_WRITEMASK_NONE) {470report_error( ctx, "Writemask expected" );471return FALSE;472}473474ctx->cur = cur;475}476else {477*writemask = TGSI_WRITEMASK_XYZW;478}479return TRUE;480}481482483/* <register_file_bracket> ::= <file> `['484*/485static boolean486parse_register_file_bracket(487struct translate_ctx *ctx,488uint *file )489{490if (!parse_file( &ctx->cur, file )) {491report_error( ctx, "Unknown register file" );492return FALSE;493}494eat_opt_white( &ctx->cur );495if (*ctx->cur != '[') {496report_error( ctx, "Expected `['" );497return FALSE;498}499ctx->cur++;500return TRUE;501}502503/* <register_file_bracket_index> ::= <register_file_bracket> <uint>504*/505static boolean506parse_register_file_bracket_index(507struct translate_ctx *ctx,508uint *file,509int *index )510{511uint uindex;512513if (!parse_register_file_bracket( ctx, file ))514return FALSE;515eat_opt_white( &ctx->cur );516if (!parse_uint( &ctx->cur, &uindex )) {517report_error( ctx, "Expected literal unsigned integer" );518return FALSE;519}520*index = (int) uindex;521return TRUE;522}523524/* Parse simple 1d register operand.525* <register_dst> ::= <register_file_bracket_index> `]'526*/527static boolean528parse_register_1d(struct translate_ctx *ctx,529uint *file,530int *index )531{532if (!parse_register_file_bracket_index( ctx, file, index ))533return FALSE;534eat_opt_white( &ctx->cur );535if (*ctx->cur != ']') {536report_error( ctx, "Expected `]'" );537return FALSE;538}539ctx->cur++;540return TRUE;541}542543struct parsed_bracket {544int index;545546uint ind_file;547int ind_index;548uint ind_comp;549uint ind_array;550};551552553static boolean554parse_register_bracket(555struct translate_ctx *ctx,556struct parsed_bracket *brackets)557{558const char *cur;559uint uindex;560561memset(brackets, 0, sizeof(struct parsed_bracket));562563eat_opt_white( &ctx->cur );564565cur = ctx->cur;566if (parse_file( &cur, &brackets->ind_file )) {567if (!parse_register_1d( ctx, &brackets->ind_file,568&brackets->ind_index ))569return FALSE;570eat_opt_white( &ctx->cur );571572if (*ctx->cur == '.') {573ctx->cur++;574eat_opt_white(&ctx->cur);575576switch (uprcase(*ctx->cur)) {577case 'X':578brackets->ind_comp = TGSI_SWIZZLE_X;579break;580case 'Y':581brackets->ind_comp = TGSI_SWIZZLE_Y;582break;583case 'Z':584brackets->ind_comp = TGSI_SWIZZLE_Z;585break;586case 'W':587brackets->ind_comp = TGSI_SWIZZLE_W;588break;589default:590report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");591return FALSE;592}593ctx->cur++;594eat_opt_white(&ctx->cur);595}596597if (*ctx->cur == '+' || *ctx->cur == '-')598parse_int( &ctx->cur, &brackets->index );599else600brackets->index = 0;601}602else {603if (!parse_uint( &ctx->cur, &uindex )) {604report_error( ctx, "Expected literal unsigned integer" );605return FALSE;606}607brackets->index = (int) uindex;608brackets->ind_file = TGSI_FILE_NULL;609brackets->ind_index = 0;610}611eat_opt_white( &ctx->cur );612if (*ctx->cur != ']') {613report_error( ctx, "Expected `]'" );614return FALSE;615}616ctx->cur++;617if (*ctx->cur == '(') {618ctx->cur++;619eat_opt_white( &ctx->cur );620if (!parse_uint( &ctx->cur, &brackets->ind_array )) {621report_error( ctx, "Expected literal unsigned integer" );622return FALSE;623}624eat_opt_white( &ctx->cur );625if (*ctx->cur != ')') {626report_error( ctx, "Expected `)'" );627return FALSE;628}629ctx->cur++;630}631return TRUE;632}633634static boolean635parse_opt_register_src_bracket(636struct translate_ctx *ctx,637struct parsed_bracket *brackets,638int *parsed_brackets)639{640const char *cur = ctx->cur;641642*parsed_brackets = 0;643644eat_opt_white( &cur );645if (cur[0] == '[') {646++cur;647ctx->cur = cur;648649if (!parse_register_bracket(ctx, brackets))650return FALSE;651652*parsed_brackets = 1;653}654655return TRUE;656}657658659/* Parse source register operand.660* <register_src> ::= <register_file_bracket_index> `]' |661* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |662* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |663* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'664*/665static boolean666parse_register_src(667struct translate_ctx *ctx,668uint *file,669struct parsed_bracket *brackets)670{671brackets->ind_comp = TGSI_SWIZZLE_X;672if (!parse_register_file_bracket( ctx, file ))673return FALSE;674if (!parse_register_bracket( ctx, brackets ))675return FALSE;676677return TRUE;678}679680struct parsed_dcl_bracket {681uint first;682uint last;683};684685static boolean686parse_register_dcl_bracket(687struct translate_ctx *ctx,688struct parsed_dcl_bracket *bracket)689{690uint uindex;691memset(bracket, 0, sizeof(struct parsed_dcl_bracket));692693eat_opt_white( &ctx->cur );694695if (!parse_uint( &ctx->cur, &uindex )) {696/* it can be an empty bracket [] which means its range697* is from 0 to some implied size */698if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {699bracket->first = 0;700bracket->last = ctx->implied_array_size - 1;701goto cleanup;702}703report_error( ctx, "Expected literal unsigned integer" );704return FALSE;705}706bracket->first = uindex;707708eat_opt_white( &ctx->cur );709710if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {711uint uindex;712713ctx->cur += 2;714eat_opt_white( &ctx->cur );715if (!parse_uint( &ctx->cur, &uindex )) {716report_error( ctx, "Expected literal integer" );717return FALSE;718}719bracket->last = (int) uindex;720eat_opt_white( &ctx->cur );721}722else {723bracket->last = bracket->first;724}725726cleanup:727if (*ctx->cur != ']') {728report_error( ctx, "Expected `]' or `..'" );729return FALSE;730}731ctx->cur++;732return TRUE;733}734735/* Parse register declaration.736* <register_dcl> ::= <register_file_bracket_index> `]' |737* <register_file_bracket_index> `..' <index> `]'738*/739static boolean740parse_register_dcl(741struct translate_ctx *ctx,742uint *file,743struct parsed_dcl_bracket *brackets,744int *num_brackets)745{746const char *cur;747748*num_brackets = 0;749750if (!parse_register_file_bracket( ctx, file ))751return FALSE;752if (!parse_register_dcl_bracket( ctx, &brackets[0] ))753return FALSE;754755*num_brackets = 1;756757cur = ctx->cur;758eat_opt_white( &cur );759760if (cur[0] == '[') {761bool is_in = *file == TGSI_FILE_INPUT;762bool is_out = *file == TGSI_FILE_OUTPUT;763764++cur;765ctx->cur = cur;766if (!parse_register_dcl_bracket( ctx, &brackets[1] ))767return FALSE;768/* for geometry shader we don't really care about769* the first brackets it's always the size of the770* input primitive. so we want to declare just771* the index relevant to the semantics which is in772* the second bracket */773774/* tessellation has similar constraints to geometry shader */775if ((ctx->processor == PIPE_SHADER_GEOMETRY && is_in) ||776(ctx->processor == PIPE_SHADER_TESS_EVAL && is_in) ||777(ctx->processor == PIPE_SHADER_TESS_CTRL && (is_in || is_out))) {778brackets[0] = brackets[1];779*num_brackets = 1;780} else {781*num_brackets = 2;782}783}784785return TRUE;786}787788789/* Parse destination register operand.*/790static boolean791parse_register_dst(792struct translate_ctx *ctx,793uint *file,794struct parsed_bracket *brackets)795{796brackets->ind_comp = TGSI_SWIZZLE_X;797if (!parse_register_file_bracket( ctx, file ))798return FALSE;799if (!parse_register_bracket( ctx, brackets ))800return FALSE;801802return TRUE;803}804805static boolean806parse_dst_operand(807struct translate_ctx *ctx,808struct tgsi_full_dst_register *dst )809{810uint file;811uint writemask;812const char *cur;813struct parsed_bracket bracket[2];814int parsed_opt_brackets;815816if (!parse_register_dst( ctx, &file, &bracket[0] ))817return FALSE;818if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))819return FALSE;820821cur = ctx->cur;822eat_opt_white( &cur );823824if (!parse_opt_writemask( ctx, &writemask ))825return FALSE;826827dst->Register.File = file;828if (parsed_opt_brackets) {829dst->Register.Dimension = 1;830dst->Dimension.Indirect = 0;831dst->Dimension.Dimension = 0;832dst->Dimension.Index = bracket[0].index;833834if (bracket[0].ind_file != TGSI_FILE_NULL) {835dst->Dimension.Indirect = 1;836dst->DimIndirect.File = bracket[0].ind_file;837dst->DimIndirect.Index = bracket[0].ind_index;838dst->DimIndirect.Swizzle = bracket[0].ind_comp;839dst->DimIndirect.ArrayID = bracket[0].ind_array;840}841bracket[0] = bracket[1];842}843dst->Register.Index = bracket[0].index;844dst->Register.WriteMask = writemask;845if (bracket[0].ind_file != TGSI_FILE_NULL) {846dst->Register.Indirect = 1;847dst->Indirect.File = bracket[0].ind_file;848dst->Indirect.Index = bracket[0].ind_index;849dst->Indirect.Swizzle = bracket[0].ind_comp;850dst->Indirect.ArrayID = bracket[0].ind_array;851}852return TRUE;853}854855static boolean856parse_optional_swizzle(857struct translate_ctx *ctx,858uint *swizzle,859boolean *parsed_swizzle,860int components)861{862const char *cur = ctx->cur;863864*parsed_swizzle = FALSE;865866eat_opt_white( &cur );867if (*cur == '.') {868int i;869870cur++;871eat_opt_white( &cur );872for (i = 0; i < components; i++) {873if (uprcase( *cur ) == 'X')874swizzle[i] = TGSI_SWIZZLE_X;875else if (uprcase( *cur ) == 'Y')876swizzle[i] = TGSI_SWIZZLE_Y;877else if (uprcase( *cur ) == 'Z')878swizzle[i] = TGSI_SWIZZLE_Z;879else if (uprcase( *cur ) == 'W')880swizzle[i] = TGSI_SWIZZLE_W;881else {882report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );883return FALSE;884}885cur++;886}887*parsed_swizzle = TRUE;888ctx->cur = cur;889}890return TRUE;891}892893static boolean894parse_src_operand(895struct translate_ctx *ctx,896struct tgsi_full_src_register *src )897{898uint file;899uint swizzle[4];900boolean parsed_swizzle;901struct parsed_bracket bracket[2];902int parsed_opt_brackets;903904if (*ctx->cur == '-') {905ctx->cur++;906eat_opt_white( &ctx->cur );907src->Register.Negate = 1;908}909910if (*ctx->cur == '|') {911ctx->cur++;912eat_opt_white( &ctx->cur );913src->Register.Absolute = 1;914}915916if (!parse_register_src(ctx, &file, &bracket[0]))917return FALSE;918if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))919return FALSE;920921src->Register.File = file;922if (parsed_opt_brackets) {923src->Register.Dimension = 1;924src->Dimension.Indirect = 0;925src->Dimension.Dimension = 0;926src->Dimension.Index = bracket[0].index;927if (bracket[0].ind_file != TGSI_FILE_NULL) {928src->Dimension.Indirect = 1;929src->DimIndirect.File = bracket[0].ind_file;930src->DimIndirect.Index = bracket[0].ind_index;931src->DimIndirect.Swizzle = bracket[0].ind_comp;932src->DimIndirect.ArrayID = bracket[0].ind_array;933}934bracket[0] = bracket[1];935}936src->Register.Index = bracket[0].index;937if (bracket[0].ind_file != TGSI_FILE_NULL) {938src->Register.Indirect = 1;939src->Indirect.File = bracket[0].ind_file;940src->Indirect.Index = bracket[0].ind_index;941src->Indirect.Swizzle = bracket[0].ind_comp;942src->Indirect.ArrayID = bracket[0].ind_array;943}944945/* Parse optional swizzle.946*/947if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) {948if (parsed_swizzle) {949src->Register.SwizzleX = swizzle[0];950src->Register.SwizzleY = swizzle[1];951src->Register.SwizzleZ = swizzle[2];952src->Register.SwizzleW = swizzle[3];953}954}955956if (src->Register.Absolute) {957eat_opt_white( &ctx->cur );958if (*ctx->cur != '|') {959report_error( ctx, "Expected `|'" );960return FALSE;961}962ctx->cur++;963}964965966return TRUE;967}968969static boolean970parse_texoffset_operand(971struct translate_ctx *ctx,972struct tgsi_texture_offset *src )973{974uint file;975uint swizzle[3];976boolean parsed_swizzle;977struct parsed_bracket bracket;978979if (!parse_register_src(ctx, &file, &bracket))980return FALSE;981982src->File = file;983src->Index = bracket.index;984985/* Parse optional swizzle.986*/987if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) {988if (parsed_swizzle) {989src->SwizzleX = swizzle[0];990src->SwizzleY = swizzle[1];991src->SwizzleZ = swizzle[2];992}993}994995return TRUE;996}997998static boolean999match_inst(const char **pcur,1000unsigned *saturate,1001unsigned *precise,1002const struct tgsi_opcode_info *info)1003{1004const char *cur = *pcur;1005const char *mnemonic = tgsi_get_opcode_name(info->opcode);10061007/* simple case: the whole string matches the instruction name */1008if (str_match_nocase_whole(&cur, mnemonic)) {1009*pcur = cur;1010*saturate = 0;1011*precise = 0;1012return TRUE;1013}10141015if (str_match_no_case(&cur, mnemonic)) {1016/* the instruction has a suffix, figure it out */1017if (str_match_no_case(&cur, "_SAT")) {1018*pcur = cur;1019*saturate = 1;1020}10211022if (str_match_no_case(&cur, "_PRECISE")) {1023*pcur = cur;1024*precise = 1;1025}10261027if (!is_digit_alpha_underscore(cur))1028return TRUE;1029}10301031return FALSE;1032}10331034static boolean1035parse_instruction(1036struct translate_ctx *ctx,1037boolean has_label )1038{1039int i;1040uint saturate = 0;1041uint precise = 0;1042const struct tgsi_opcode_info *info;1043struct tgsi_full_instruction inst;1044const char *cur;1045uint advance;10461047inst = tgsi_default_full_instruction();10481049/* Parse instruction name.1050*/1051eat_opt_white( &ctx->cur );1052for (i = 0; i < TGSI_OPCODE_LAST; i++) {1053cur = ctx->cur;10541055info = tgsi_get_opcode_info( i );1056if (match_inst(&cur, &saturate, &precise, info)) {1057if (info->num_dst + info->num_src + info->is_tex == 0) {1058ctx->cur = cur;1059break;1060}1061else if (*cur == '\0' || eat_white( &cur )) {1062ctx->cur = cur;1063break;1064}1065}1066}1067if (i == TGSI_OPCODE_LAST) {1068if (has_label)1069report_error( ctx, "Unknown opcode" );1070else1071report_error( ctx, "Expected `DCL', `IMM' or a label" );1072return FALSE;1073}10741075inst.Instruction.Opcode = i;1076inst.Instruction.Saturate = saturate;1077inst.Instruction.Precise = precise;1078inst.Instruction.NumDstRegs = info->num_dst;1079inst.Instruction.NumSrcRegs = info->num_src;10801081if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {1082/*1083* These are not considered tex opcodes here (no additional1084* target argument) however we're required to set the Texture1085* bit so we can set the number of tex offsets.1086*/1087inst.Instruction.Texture = 1;1088inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;1089}10901091if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) ||1092i == TGSI_OPCODE_RESQ) {1093inst.Instruction.Memory = 1;1094inst.Memory.Qualifier = 0;1095}10961097assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS);1098assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS);10991100/* Parse instruction operands.1101*/1102for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {1103if (i > 0) {1104eat_opt_white( &ctx->cur );1105if (*ctx->cur != ',') {1106report_error( ctx, "Expected `,'" );1107return FALSE;1108}1109ctx->cur++;1110eat_opt_white( &ctx->cur );1111}11121113if (i < info->num_dst) {1114if (!parse_dst_operand( ctx, &inst.Dst[i] ))1115return FALSE;1116}1117else if (i < info->num_dst + info->num_src) {1118if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))1119return FALSE;1120}1121else {1122uint j;11231124for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {1125if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {1126inst.Instruction.Texture = 1;1127inst.Texture.Texture = j;1128break;1129}1130}1131if (j == TGSI_TEXTURE_COUNT) {1132report_error( ctx, "Expected texture target" );1133return FALSE;1134}1135}1136}11371138cur = ctx->cur;1139eat_opt_white( &cur );1140for (i = 0; inst.Instruction.Texture && *cur == ',' && i < TGSI_FULL_MAX_TEX_OFFSETS; i++) {1141cur++;1142eat_opt_white( &cur );1143ctx->cur = cur;1144if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] ))1145return FALSE;1146cur = ctx->cur;1147eat_opt_white( &cur );1148}1149inst.Texture.NumOffsets = i;11501151cur = ctx->cur;1152eat_opt_white(&cur);11531154for (; inst.Instruction.Memory && *cur == ',';1155ctx->cur = cur, eat_opt_white(&cur)) {1156int j;11571158cur++;1159eat_opt_white(&cur);11601161j = str_match_name_from_array(&cur, tgsi_memory_names,1162ARRAY_SIZE(tgsi_memory_names));1163if (j >= 0) {1164inst.Memory.Qualifier |= 1U << j;1165continue;1166}11671168j = str_match_name_from_array(&cur, tgsi_texture_names,1169ARRAY_SIZE(tgsi_texture_names));1170if (j >= 0) {1171inst.Memory.Texture = j;1172continue;1173}11741175j = str_match_format(&cur);1176if (j >= 0) {1177inst.Memory.Format = j;1178continue;1179}11801181ctx->cur = cur;1182report_error(ctx, "Expected memory qualifier, texture target, or format\n");1183return FALSE;1184}11851186cur = ctx->cur;1187eat_opt_white( &cur );1188if (info->is_branch && *cur == ':') {1189uint target;11901191cur++;1192eat_opt_white( &cur );1193if (!parse_uint( &cur, &target )) {1194report_error( ctx, "Expected a label" );1195return FALSE;1196}1197inst.Instruction.Label = 1;1198inst.Label.Label = target;1199ctx->cur = cur;1200}12011202advance = tgsi_build_full_instruction(1203&inst,1204ctx->tokens_cur,1205ctx->header,1206(uint) (ctx->tokens_end - ctx->tokens_cur) );1207if (advance == 0)1208return FALSE;1209ctx->tokens_cur += advance;12101211return TRUE;1212}12131214/* parses a 4-touple of the form {x, y, z, w}1215* where x, y, z, w are numbers */1216static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,1217union tgsi_immediate_data *values)1218{1219unsigned i;1220int ret;12211222eat_opt_white( &ctx->cur );1223if (*ctx->cur != '{') {1224report_error( ctx, "Expected `{'" );1225return FALSE;1226}1227ctx->cur++;1228for (i = 0; i < 4; i++) {1229eat_opt_white( &ctx->cur );1230if (i > 0) {1231if (*ctx->cur != ',') {1232report_error( ctx, "Expected `,'" );1233return FALSE;1234}1235ctx->cur++;1236eat_opt_white( &ctx->cur );1237}12381239switch (type) {1240case TGSI_IMM_FLOAT64:1241ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint);1242i++;1243break;1244case TGSI_IMM_INT64:1245ret = parse_int64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);1246i++;1247break;1248case TGSI_IMM_UINT64:1249ret = parse_uint64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);1250i++;1251break;1252case TGSI_IMM_FLOAT32:1253ret = parse_float(&ctx->cur, &values[i].Float);1254break;1255case TGSI_IMM_UINT32:1256ret = parse_uint(&ctx->cur, &values[i].Uint);1257break;1258case TGSI_IMM_INT32:1259ret = parse_int(&ctx->cur, &values[i].Int);1260break;1261default:1262assert(0);1263ret = FALSE;1264break;1265}12661267if (!ret) {1268report_error( ctx, "Expected immediate constant" );1269return FALSE;1270}1271}1272eat_opt_white( &ctx->cur );1273if (*ctx->cur != '}') {1274report_error( ctx, "Expected `}'" );1275return FALSE;1276}1277ctx->cur++;12781279return TRUE;1280}12811282static boolean parse_declaration( struct translate_ctx *ctx )1283{1284struct tgsi_full_declaration decl;1285uint file;1286struct parsed_dcl_bracket brackets[2];1287int num_brackets;1288uint writemask;1289const char *cur, *cur2;1290uint advance;1291boolean is_vs_input;12921293if (!eat_white( &ctx->cur )) {1294report_error( ctx, "Syntax error" );1295return FALSE;1296}1297if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))1298return FALSE;1299if (!parse_opt_writemask( ctx, &writemask ))1300return FALSE;13011302decl = tgsi_default_full_declaration();1303decl.Declaration.File = file;1304decl.Declaration.UsageMask = writemask;13051306if (num_brackets == 1) {1307decl.Range.First = brackets[0].first;1308decl.Range.Last = brackets[0].last;1309} else {1310decl.Range.First = brackets[1].first;1311decl.Range.Last = brackets[1].last;13121313decl.Declaration.Dimension = 1;1314decl.Dim.Index2D = brackets[0].first;1315}13161317is_vs_input = (file == TGSI_FILE_INPUT &&1318ctx->processor == PIPE_SHADER_VERTEX);13191320cur = ctx->cur;1321eat_opt_white( &cur );1322if (*cur == ',') {1323cur2 = cur;1324cur2++;1325eat_opt_white( &cur2 );1326if (str_match_nocase_whole( &cur2, "ARRAY" )) {1327int arrayid;1328if (*cur2 != '(') {1329report_error( ctx, "Expected `('" );1330return FALSE;1331}1332cur2++;1333eat_opt_white( &cur2 );1334if (!parse_int( &cur2, &arrayid )) {1335report_error( ctx, "Expected `,'" );1336return FALSE;1337}1338eat_opt_white( &cur2 );1339if (*cur2 != ')') {1340report_error( ctx, "Expected `)'" );1341return FALSE;1342}1343cur2++;1344decl.Declaration.Array = 1;1345decl.Array.ArrayID = arrayid;1346ctx->cur = cur = cur2;1347}1348}13491350if (*cur == ',' && !is_vs_input) {1351uint i, j;13521353cur++;1354eat_opt_white( &cur );1355if (file == TGSI_FILE_IMAGE) {1356for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {1357if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {1358decl.Image.Resource = i;1359break;1360}1361}1362if (i == TGSI_TEXTURE_COUNT) {1363report_error(ctx, "Expected texture target");1364return FALSE;1365}13661367cur2 = cur;1368eat_opt_white(&cur2);1369while (*cur2 == ',') {1370cur2++;1371eat_opt_white(&cur2);1372if (str_match_nocase_whole(&cur2, "RAW")) {1373decl.Image.Raw = 1;13741375} else if (str_match_nocase_whole(&cur2, "WR")) {1376decl.Image.Writable = 1;13771378} else {1379int format = str_match_format(&cur2);1380if (format < 0)1381break;13821383decl.Image.Format = format;1384}1385cur = cur2;1386eat_opt_white(&cur2);1387}13881389ctx->cur = cur;13901391} else if (file == TGSI_FILE_SAMPLER_VIEW) {1392for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {1393if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {1394decl.SamplerView.Resource = i;1395break;1396}1397}1398if (i == TGSI_TEXTURE_COUNT) {1399report_error(ctx, "Expected texture target");1400return FALSE;1401}1402eat_opt_white( &cur );1403if (*cur != ',') {1404report_error( ctx, "Expected `,'" );1405return FALSE;1406}1407++cur;1408eat_opt_white( &cur );1409for (j = 0; j < 4; ++j) {1410for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) {1411if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) {1412switch (j) {1413case 0:1414decl.SamplerView.ReturnTypeX = i;1415break;1416case 1:1417decl.SamplerView.ReturnTypeY = i;1418break;1419case 2:1420decl.SamplerView.ReturnTypeZ = i;1421break;1422case 3:1423decl.SamplerView.ReturnTypeW = i;1424break;1425default:1426assert(0);1427}1428break;1429}1430}1431if (i == TGSI_RETURN_TYPE_COUNT) {1432if (j == 0 || j > 2) {1433report_error(ctx, "Expected type name");1434return FALSE;1435}1436break;1437} else {1438cur2 = cur;1439eat_opt_white( &cur2 );1440if (*cur2 == ',') {1441cur2++;1442eat_opt_white( &cur2 );1443cur = cur2;1444continue;1445} else1446break;1447}1448}1449if (j < 4) {1450decl.SamplerView.ReturnTypeY =1451decl.SamplerView.ReturnTypeZ =1452decl.SamplerView.ReturnTypeW =1453decl.SamplerView.ReturnTypeX;1454}1455ctx->cur = cur;1456} else if (file == TGSI_FILE_BUFFER) {1457if (str_match_nocase_whole(&cur, "ATOMIC")) {1458decl.Declaration.Atomic = 1;1459ctx->cur = cur;1460}1461} else if (file == TGSI_FILE_MEMORY) {1462if (str_match_nocase_whole(&cur, "GLOBAL")) {1463/* Note this is a no-op global is the default */1464decl.Declaration.MemType = TGSI_MEMORY_TYPE_GLOBAL;1465ctx->cur = cur;1466} else if (str_match_nocase_whole(&cur, "SHARED")) {1467decl.Declaration.MemType = TGSI_MEMORY_TYPE_SHARED;1468ctx->cur = cur;1469} else if (str_match_nocase_whole(&cur, "PRIVATE")) {1470decl.Declaration.MemType = TGSI_MEMORY_TYPE_PRIVATE;1471ctx->cur = cur;1472} else if (str_match_nocase_whole(&cur, "INPUT")) {1473decl.Declaration.MemType = TGSI_MEMORY_TYPE_INPUT;1474ctx->cur = cur;1475}1476} else {1477if (str_match_nocase_whole(&cur, "LOCAL")) {1478decl.Declaration.Local = 1;1479ctx->cur = cur;1480}14811482cur = ctx->cur;1483eat_opt_white( &cur );1484if (*cur == ',') {1485cur++;1486eat_opt_white( &cur );14871488for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {1489if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {1490uint index;14911492cur2 = cur;1493eat_opt_white( &cur2 );1494if (*cur2 == '[') {1495cur2++;1496eat_opt_white( &cur2 );1497if (!parse_uint( &cur2, &index )) {1498report_error( ctx, "Expected literal integer" );1499return FALSE;1500}1501eat_opt_white( &cur2 );1502if (*cur2 != ']') {1503report_error( ctx, "Expected `]'" );1504return FALSE;1505}1506cur2++;15071508decl.Semantic.Index = index;15091510cur = cur2;1511}15121513decl.Declaration.Semantic = 1;1514decl.Semantic.Name = i;15151516ctx->cur = cur;1517break;1518}1519}1520}1521}1522}15231524cur = ctx->cur;1525eat_opt_white( &cur );1526if (*cur == ',' &&1527file == TGSI_FILE_OUTPUT && ctx->processor == PIPE_SHADER_GEOMETRY) {1528cur++;1529eat_opt_white(&cur);1530if (str_match_nocase_whole(&cur, "STREAM")) {1531uint stream[4];15321533eat_opt_white(&cur);1534if (*cur != '(') {1535report_error(ctx, "Expected '('");1536return FALSE;1537}1538cur++;15391540for (int i = 0; i < 4; ++i) {1541eat_opt_white(&cur);1542if (!parse_uint(&cur, &stream[i])) {1543report_error(ctx, "Expected literal integer");1544return FALSE;1545}15461547eat_opt_white(&cur);1548if (i < 3) {1549if (*cur != ',') {1550report_error(ctx, "Expected ','");1551return FALSE;1552}1553cur++;1554}1555}15561557if (*cur != ')') {1558report_error(ctx, "Expected ')'");1559return FALSE;1560}1561cur++;15621563decl.Semantic.StreamX = stream[0];1564decl.Semantic.StreamY = stream[1];1565decl.Semantic.StreamZ = stream[2];1566decl.Semantic.StreamW = stream[3];15671568ctx->cur = cur;1569}1570}15711572cur = ctx->cur;1573eat_opt_white( &cur );1574if (*cur == ',' && !is_vs_input) {1575uint i;15761577cur++;1578eat_opt_white( &cur );1579for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {1580if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {1581decl.Declaration.Interpolate = 1;1582decl.Interp.Interpolate = i;15831584ctx->cur = cur;1585break;1586}1587}1588}15891590cur = ctx->cur;1591eat_opt_white( &cur );1592if (*cur == ',' && !is_vs_input) {1593uint i;15941595cur++;1596eat_opt_white( &cur );1597for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) {1598if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) {1599decl.Interp.Location = i;16001601ctx->cur = cur;1602break;1603}1604}1605}16061607cur = ctx->cur;1608eat_opt_white( &cur );1609if (*cur == ',' && !is_vs_input) {1610cur++;1611eat_opt_white( &cur );1612if (str_match_nocase_whole( &cur, tgsi_invariant_name )) {1613decl.Declaration.Invariant = 1;1614ctx->cur = cur;1615} else {1616report_error( ctx, "Expected semantic, interpolate attribute, or invariant ");1617return FALSE;1618}1619}16201621advance = tgsi_build_full_declaration(1622&decl,1623ctx->tokens_cur,1624ctx->header,1625(uint) (ctx->tokens_end - ctx->tokens_cur) );16261627if (advance == 0)1628return FALSE;1629ctx->tokens_cur += advance;16301631return TRUE;1632}16331634static boolean parse_immediate( struct translate_ctx *ctx )1635{1636struct tgsi_full_immediate imm;1637uint advance;1638uint type;16391640if (*ctx->cur == '[') {1641uint uindex;16421643++ctx->cur;16441645eat_opt_white( &ctx->cur );1646if (!parse_uint( &ctx->cur, &uindex )) {1647report_error( ctx, "Expected literal unsigned integer" );1648return FALSE;1649}16501651if (uindex != ctx->num_immediates) {1652report_error( ctx, "Immediates must be sorted" );1653return FALSE;1654}16551656eat_opt_white( &ctx->cur );1657if (*ctx->cur != ']') {1658report_error( ctx, "Expected `]'" );1659return FALSE;1660}16611662ctx->cur++;1663}16641665if (!eat_white( &ctx->cur )) {1666report_error( ctx, "Syntax error" );1667return FALSE;1668}1669for (type = 0; type < ARRAY_SIZE(tgsi_immediate_type_names); ++type) {1670if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))1671break;1672}1673if (type == ARRAY_SIZE(tgsi_immediate_type_names)) {1674report_error( ctx, "Expected immediate type" );1675return FALSE;1676}16771678imm = tgsi_default_full_immediate();1679imm.Immediate.NrTokens += 4;1680imm.Immediate.DataType = type;1681parse_immediate_data(ctx, type, imm.u);16821683advance = tgsi_build_full_immediate(1684&imm,1685ctx->tokens_cur,1686ctx->header,1687(uint) (ctx->tokens_end - ctx->tokens_cur) );1688if (advance == 0)1689return FALSE;1690ctx->tokens_cur += advance;16911692ctx->num_immediates++;16931694return TRUE;1695}16961697static boolean1698parse_primitive( const char **pcur, uint *primitive )1699{1700uint i;17011702for (i = 0; i < PIPE_PRIM_MAX; i++) {1703const char *cur = *pcur;17041705if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {1706*primitive = i;1707*pcur = cur;1708return TRUE;1709}1710}1711return FALSE;1712}17131714static boolean1715parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )1716{1717uint i;17181719for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_origin_names); i++) {1720const char *cur = *pcur;17211722if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {1723*fs_coord_origin = i;1724*pcur = cur;1725return TRUE;1726}1727}1728return FALSE;1729}17301731static boolean1732parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )1733{1734uint i;17351736for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_pixel_center_names); i++) {1737const char *cur = *pcur;17381739if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {1740*fs_coord_pixel_center = i;1741*pcur = cur;1742return TRUE;1743}1744}1745return FALSE;1746}17471748static boolean1749parse_property_next_shader( const char **pcur, uint *next_shader )1750{1751uint i;17521753for (i = 0; i < ARRAY_SIZE(tgsi_processor_type_names); i++) {1754const char *cur = *pcur;17551756if (str_match_nocase_whole( &cur, tgsi_processor_type_names[i])) {1757*next_shader = i;1758*pcur = cur;1759return TRUE;1760}1761}1762return FALSE;1763}17641765static boolean parse_property( struct translate_ctx *ctx )1766{1767struct tgsi_full_property prop;1768uint property_name;1769uint values[8];1770uint advance;1771char id[64];17721773if (!eat_white( &ctx->cur )) {1774report_error( ctx, "Syntax error" );1775return FALSE;1776}1777if (!parse_identifier( &ctx->cur, id, sizeof(id) )) {1778report_error( ctx, "Syntax error" );1779return FALSE;1780}1781for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;1782++property_name) {1783if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {1784break;1785}1786}1787if (property_name >= TGSI_PROPERTY_COUNT) {1788debug_printf( "\nError: Unknown property : '%s'", id );1789return FALSE;1790}17911792eat_opt_white( &ctx->cur );1793switch(property_name) {1794case TGSI_PROPERTY_GS_INPUT_PRIM:1795case TGSI_PROPERTY_GS_OUTPUT_PRIM:1796if (!parse_primitive(&ctx->cur, &values[0] )) {1797report_error( ctx, "Unknown primitive name as property!" );1798return FALSE;1799}1800if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&1801ctx->processor == PIPE_SHADER_GEOMETRY) {1802ctx->implied_array_size = u_vertices_per_prim(values[0]);1803}1804break;1805case TGSI_PROPERTY_FS_COORD_ORIGIN:1806if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {1807report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );1808return FALSE;1809}1810break;1811case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:1812if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {1813report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );1814return FALSE;1815}1816break;1817case TGSI_PROPERTY_NEXT_SHADER:1818if (!parse_property_next_shader(&ctx->cur, &values[0] )) {1819report_error( ctx, "Unknown next shader property value." );1820return FALSE;1821}1822break;1823case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:1824default:1825if (!parse_uint(&ctx->cur, &values[0] )) {1826report_error( ctx, "Expected unsigned integer as property!" );1827return FALSE;1828}1829}18301831prop = tgsi_default_full_property();1832prop.Property.PropertyName = property_name;1833prop.Property.NrTokens += 1;1834prop.u[0].Data = values[0];18351836advance = tgsi_build_full_property(1837&prop,1838ctx->tokens_cur,1839ctx->header,1840(uint) (ctx->tokens_end - ctx->tokens_cur) );1841if (advance == 0)1842return FALSE;1843ctx->tokens_cur += advance;18441845return TRUE;1846}184718481849static boolean translate( struct translate_ctx *ctx )1850{1851eat_opt_white( &ctx->cur );1852if (!parse_header( ctx ))1853return FALSE;18541855if (ctx->processor == PIPE_SHADER_TESS_CTRL ||1856ctx->processor == PIPE_SHADER_TESS_EVAL)1857ctx->implied_array_size = 32;18581859while (*ctx->cur != '\0') {1860uint label_val = 0;1861if (!eat_white( &ctx->cur )) {1862report_error( ctx, "Syntax error" );1863return FALSE;1864}18651866if (*ctx->cur == '\0')1867break;1868if (parse_label( ctx, &label_val )) {1869if (!parse_instruction( ctx, TRUE ))1870return FALSE;1871}1872else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {1873if (!parse_declaration( ctx ))1874return FALSE;1875}1876else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {1877if (!parse_immediate( ctx ))1878return FALSE;1879}1880else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {1881if (!parse_property( ctx ))1882return FALSE;1883}1884else if (!parse_instruction( ctx, FALSE )) {1885return FALSE;1886}1887}18881889return TRUE;1890}18911892boolean1893tgsi_text_translate(1894const char *text,1895struct tgsi_token *tokens,1896uint num_tokens )1897{1898struct translate_ctx ctx = {0};18991900ctx.text = text;1901ctx.cur = text;1902ctx.tokens = tokens;1903ctx.tokens_cur = tokens;1904ctx.tokens_end = tokens + num_tokens;19051906if (!translate( &ctx ))1907return FALSE;19081909return tgsi_sanity_check( tokens );1910}191119121913