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