tgsi_parse.c revision baa7ff47d548cdcc1ea68657ee1b0500f78041be
1/************************************************************************** 2 * 3 * Copyright 2007 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 "pipe/p_shader_tokens.h" 30#include "tgsi_parse.h" 31#include "tgsi_build.h" 32#include "util/u_memory.h" 33 34void 35tgsi_full_token_init( 36 union tgsi_full_token *full_token ) 37{ 38 full_token->Token.Type = TGSI_TOKEN_TYPE_DECLARATION; 39} 40 41void 42tgsi_full_token_free( 43 union tgsi_full_token *full_token ) 44{ 45 if( full_token->Token.Type == TGSI_TOKEN_TYPE_IMMEDIATE ) { 46 FREE( (void *) full_token->FullImmediate.u.Pointer ); 47 } 48} 49 50unsigned 51tgsi_parse_init( 52 struct tgsi_parse_context *ctx, 53 const struct tgsi_token *tokens ) 54{ 55 ctx->FullVersion.Version = *(struct tgsi_version *) &tokens[0]; 56 if( ctx->FullVersion.Version.MajorVersion > 1 ) { 57 return TGSI_PARSE_ERROR; 58 } 59 60 ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[1]; 61 if( ctx->FullHeader.Header.HeaderSize >= 2 ) { 62 ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[2]; 63 } 64 else { 65 ctx->FullHeader.Processor = tgsi_default_processor(); 66 } 67 68 ctx->Tokens = tokens; 69 ctx->Position = 1 + ctx->FullHeader.Header.HeaderSize; 70 71 tgsi_full_token_init( &ctx->FullToken ); 72 73 return TGSI_PARSE_OK; 74} 75 76void 77tgsi_parse_free( 78 struct tgsi_parse_context *ctx ) 79{ 80 tgsi_full_token_free( &ctx->FullToken ); 81} 82 83boolean 84tgsi_parse_end_of_tokens( 85 struct tgsi_parse_context *ctx ) 86{ 87 return ctx->Position >= 88 1 + ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize; 89} 90 91 92/** 93 * This function is used to avoid and work-around type punning/aliasing 94 * warnings. The warnings seem harmless on x86 but on PPC they cause 95 * real failures. 96 */ 97static INLINE void 98copy_token(void *dst, const void *src) 99{ 100 memcpy(dst, src, 4); 101} 102 103 104/** 105 * Get next 4-byte token, return it at address specified by 'token' 106 */ 107static void 108next_token( 109 struct tgsi_parse_context *ctx, 110 void *token ) 111{ 112 assert( !tgsi_parse_end_of_tokens( ctx ) ); 113 copy_token(token, &ctx->Tokens[ctx->Position]); 114 ctx->Position++; 115} 116 117 118void 119tgsi_parse_token( 120 struct tgsi_parse_context *ctx ) 121{ 122 struct tgsi_token token; 123 unsigned i; 124 125 tgsi_full_token_free( &ctx->FullToken ); 126 tgsi_full_token_init( &ctx->FullToken ); 127 128 next_token( ctx, &token ); 129 130 switch( token.Type ) { 131 case TGSI_TOKEN_TYPE_DECLARATION: 132 { 133 struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration; 134 135 *decl = tgsi_default_full_declaration(); 136 copy_token(&decl->Declaration, &token); 137 138 next_token( ctx, &decl->DeclarationRange ); 139 140 if( decl->Declaration.Semantic ) { 141 next_token( ctx, &decl->Semantic ); 142 } 143 144 break; 145 } 146 147 case TGSI_TOKEN_TYPE_IMMEDIATE: 148 { 149 struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate; 150 151 *imm = tgsi_default_full_immediate(); 152 copy_token(&imm->Immediate, &token); 153 assert( !imm->Immediate.Extended ); 154 155 switch (imm->Immediate.DataType) { 156 case TGSI_IMM_FLOAT32: 157 { 158 uint imm_count = imm->Immediate.NrTokens - 1; 159 struct tgsi_immediate_float32 *data; 160 161 data = (struct tgsi_immediate_float32 *) MALLOC(sizeof(struct tgsi_immediate_float32) * imm_count); 162 if (data) { 163 for (i = 0; i < imm_count; i++) { 164 next_token(ctx, &data[i]); 165 } 166 imm->u.ImmediateFloat32 = data; 167 } 168 } 169 break; 170 171 default: 172 assert( 0 ); 173 } 174 175 break; 176 } 177 178 case TGSI_TOKEN_TYPE_INSTRUCTION: 179 { 180 struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction; 181 unsigned extended; 182 183 *inst = tgsi_default_full_instruction(); 184 copy_token(&inst->Instruction, &token); 185 extended = inst->Instruction.Extended; 186 187 while( extended ) { 188 struct tgsi_src_register_ext token; 189 190 next_token( ctx, &token ); 191 192 switch( token.Type ) { 193 case TGSI_INSTRUCTION_EXT_TYPE_NV: 194 copy_token(&inst->InstructionExtNv, &token); 195 break; 196 197 case TGSI_INSTRUCTION_EXT_TYPE_LABEL: 198 copy_token(&inst->InstructionExtLabel, &token); 199 break; 200 201 case TGSI_INSTRUCTION_EXT_TYPE_TEXTURE: 202 copy_token(&inst->InstructionExtTexture, &token); 203 break; 204 205 default: 206 assert( 0 ); 207 } 208 209 extended = token.Extended; 210 } 211 212 assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS ); 213 214 for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) { 215 unsigned extended; 216 217 next_token( ctx, &inst->FullDstRegisters[i].DstRegister ); 218 219 /* 220 * No support for indirect or multi-dimensional addressing. 221 */ 222 assert( !inst->FullDstRegisters[i].DstRegister.Dimension ); 223 224 extended = inst->FullDstRegisters[i].DstRegister.Extended; 225 226 while( extended ) { 227 struct tgsi_src_register_ext token; 228 229 next_token( ctx, &token ); 230 231 switch( token.Type ) { 232 case TGSI_DST_REGISTER_EXT_TYPE_CONDCODE: 233 copy_token(&inst->FullDstRegisters[i].DstRegisterExtConcode, 234 &token); 235 break; 236 237 case TGSI_DST_REGISTER_EXT_TYPE_MODULATE: 238 copy_token(&inst->FullDstRegisters[i].DstRegisterExtModulate, 239 &token); 240 break; 241 242 default: 243 assert( 0 ); 244 } 245 246 extended = token.Extended; 247 } 248 249 if( inst->FullDstRegisters[i].DstRegister.Indirect ) { 250 next_token( ctx, &inst->FullDstRegisters[i].DstRegisterInd ); 251 252 /* 253 * No support for indirect or multi-dimensional addressing. 254 */ 255 assert( !inst->FullDstRegisters[i].DstRegisterInd.Indirect ); 256 assert( !inst->FullDstRegisters[i].DstRegisterInd.Dimension ); 257 assert( !inst->FullDstRegisters[i].DstRegisterInd.Extended ); 258 } 259 } 260 261 assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS ); 262 263 for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) { 264 unsigned extended; 265 266 next_token( ctx, &inst->FullSrcRegisters[i].SrcRegister ); 267 268 extended = inst->FullSrcRegisters[i].SrcRegister.Extended; 269 270 while( extended ) { 271 struct tgsi_src_register_ext token; 272 273 next_token( ctx, &token ); 274 275 switch( token.Type ) { 276 case TGSI_SRC_REGISTER_EXT_TYPE_SWZ: 277 copy_token(&inst->FullSrcRegisters[i].SrcRegisterExtSwz, 278 &token); 279 break; 280 281 case TGSI_SRC_REGISTER_EXT_TYPE_MOD: 282 copy_token(&inst->FullSrcRegisters[i].SrcRegisterExtMod, 283 &token); 284 break; 285 286 default: 287 assert( 0 ); 288 } 289 290 extended = token.Extended; 291 } 292 293 if( inst->FullSrcRegisters[i].SrcRegister.Indirect ) { 294 next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterInd ); 295 296 /* 297 * No support for indirect or multi-dimensional addressing. 298 */ 299 assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Indirect ); 300 assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Dimension ); 301 assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Extended ); 302 } 303 304 if( inst->FullSrcRegisters[i].SrcRegister.Dimension ) { 305 next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterDim ); 306 307 /* 308 * No support for multi-dimensional addressing. 309 */ 310 assert( !inst->FullSrcRegisters[i].SrcRegisterDim.Dimension ); 311 assert( !inst->FullSrcRegisters[i].SrcRegisterDim.Extended ); 312 313 if( inst->FullSrcRegisters[i].SrcRegisterDim.Indirect ) { 314 next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterDimInd ); 315 316 /* 317 * No support for indirect or multi-dimensional addressing. 318 */ 319 assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Indirect ); 320 assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Dimension ); 321 assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Extended ); 322 } 323 } 324 } 325 326 break; 327 } 328 329 default: 330 assert( 0 ); 331 } 332} 333 334 335unsigned 336tgsi_num_tokens(const struct tgsi_token *tokens) 337{ 338 struct tgsi_parse_context ctx; 339 if (tgsi_parse_init(&ctx, tokens) == TGSI_PARSE_OK) { 340 unsigned len = (ctx.FullHeader.Header.HeaderSize + 341 ctx.FullHeader.Header.BodySize + 342 1); 343 return len; 344 } 345 return 0; 346} 347 348 349/** 350 * Make a new copy of a token array. 351 */ 352struct tgsi_token * 353tgsi_dup_tokens(const struct tgsi_token *tokens) 354{ 355 unsigned n = tgsi_num_tokens(tokens); 356 unsigned bytes = n * sizeof(struct tgsi_token); 357 struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes); 358 if (new_tokens) 359 memcpy(new_tokens, tokens, bytes); 360 return new_tokens; 361} 362