tgsi_parse.c revision bdbe77f9c6f06cfaa155f27c2ade3c523d7fbea7
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 "util/u_memory.h"
32
33unsigned
34tgsi_parse_init(
35   struct tgsi_parse_context *ctx,
36   const struct tgsi_token *tokens )
37{
38   ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[0];
39   if( ctx->FullHeader.Header.HeaderSize >= 2 ) {
40      ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[1];
41   }
42   else {
43      return TGSI_PARSE_ERROR;
44   }
45
46   ctx->Tokens = tokens;
47   ctx->Position = ctx->FullHeader.Header.HeaderSize;
48
49   return TGSI_PARSE_OK;
50}
51
52void
53tgsi_parse_free(
54   struct tgsi_parse_context *ctx )
55{
56}
57
58boolean
59tgsi_parse_end_of_tokens(
60   struct tgsi_parse_context *ctx )
61{
62   return ctx->Position >=
63      ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize;
64}
65
66
67/**
68 * This function is used to avoid and work-around type punning/aliasing
69 * warnings.  The warnings seem harmless on x86 but on PPC they cause
70 * real failures.
71 */
72static INLINE void
73copy_token(void *dst, const void *src)
74{
75   memcpy(dst, src, 4);
76}
77
78
79/**
80 * Get next 4-byte token, return it at address specified by 'token'
81 */
82static void
83next_token(
84   struct tgsi_parse_context *ctx,
85   void *token )
86{
87   assert( !tgsi_parse_end_of_tokens( ctx ) );
88   copy_token(token, &ctx->Tokens[ctx->Position]);
89   ctx->Position++;
90}
91
92
93void
94tgsi_parse_token(
95   struct tgsi_parse_context *ctx )
96{
97   struct tgsi_token token;
98   unsigned i;
99
100   next_token( ctx, &token );
101
102   switch( token.Type ) {
103   case TGSI_TOKEN_TYPE_DECLARATION:
104   {
105      struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration;
106
107      memset(decl, 0, sizeof *decl);
108      copy_token(&decl->Declaration, &token);
109
110      next_token( ctx, &decl->Range );
111
112      if (decl->Declaration.Dimension) {
113         next_token(ctx, &decl->Dim);
114      }
115
116      if( decl->Declaration.Semantic ) {
117         next_token( ctx, &decl->Semantic );
118      }
119
120      if (decl->Declaration.File == TGSI_FILE_IMMEDIATE_ARRAY) {
121         unsigned i, j;
122         decl->ImmediateData.u = (union tgsi_immediate_data*)
123                                 &ctx->Tokens[ctx->Position];
124         for (i = 0; i <= decl->Range.Last; ++i) {
125            for (j = 0; j < 4; ++j) {
126               ctx->Position++;
127            }
128         }
129      }
130
131      if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
132         next_token(ctx, &decl->Resource);
133      }
134
135      break;
136   }
137
138   case TGSI_TOKEN_TYPE_IMMEDIATE:
139   {
140      struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate;
141      uint imm_count;
142
143      memset(imm, 0, sizeof *imm);
144      copy_token(&imm->Immediate, &token);
145
146      imm_count = imm->Immediate.NrTokens - 1;
147
148      switch (imm->Immediate.DataType) {
149      case TGSI_IMM_FLOAT32:
150         for (i = 0; i < imm_count; i++) {
151            next_token(ctx, &imm->u[i].Float);
152         }
153         break;
154
155      case TGSI_IMM_UINT32:
156         for (i = 0; i < imm_count; i++) {
157            next_token(ctx, &imm->u[i].Uint);
158         }
159         break;
160
161      case TGSI_IMM_INT32:
162         for (i = 0; i < imm_count; i++) {
163            next_token(ctx, &imm->u[i].Int);
164         }
165         break;
166
167      default:
168         assert( 0 );
169      }
170
171      break;
172   }
173
174   case TGSI_TOKEN_TYPE_INSTRUCTION:
175   {
176      struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction;
177
178      memset(inst, 0, sizeof *inst);
179      copy_token(&inst->Instruction, &token);
180
181      if (inst->Instruction.Predicate) {
182         next_token(ctx, &inst->Predicate);
183      }
184
185      if (inst->Instruction.Label) {
186         next_token( ctx, &inst->Label);
187      }
188
189      if (inst->Instruction.Texture) {
190         next_token( ctx, &inst->Texture);
191      }
192
193      assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS );
194
195      for(  i = 0; i < inst->Instruction.NumDstRegs; i++ ) {
196
197         next_token( ctx, &inst->Dst[i].Register );
198
199         if( inst->Dst[i].Register.Indirect ) {
200            next_token( ctx, &inst->Dst[i].Indirect );
201
202            /*
203             * No support for indirect or multi-dimensional addressing.
204             */
205            assert( !inst->Dst[i].Indirect.Dimension );
206            assert( !inst->Dst[i].Indirect.Indirect );
207         }
208         if( inst->Dst[i].Register.Dimension ) {
209            next_token( ctx, &inst->Dst[i].Dimension );
210
211            /*
212             * No support for multi-dimensional addressing.
213             */
214            assert( !inst->Dst[i].Dimension.Dimension );
215
216            if( inst->Dst[i].Dimension.Indirect ) {
217               next_token( ctx, &inst->Dst[i].DimIndirect );
218
219               /*
220                * No support for indirect or multi-dimensional addressing.
221                */
222               assert( !inst->Dst[i].Indirect.Indirect );
223               assert( !inst->Dst[i].Indirect.Dimension );
224            }
225         }
226      }
227
228      assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS );
229
230      for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) {
231
232         next_token( ctx, &inst->Src[i].Register );
233
234         if( inst->Src[i].Register.Indirect ) {
235            next_token( ctx, &inst->Src[i].Indirect );
236
237            /*
238             * No support for indirect or multi-dimensional addressing.
239             */
240            assert( !inst->Src[i].Indirect.Indirect );
241            assert( !inst->Src[i].Indirect.Dimension );
242         }
243
244         if( inst->Src[i].Register.Dimension ) {
245            next_token( ctx, &inst->Src[i].Dimension );
246
247            /*
248             * No support for multi-dimensional addressing.
249             */
250            assert( !inst->Src[i].Dimension.Dimension );
251
252            if( inst->Src[i].Dimension.Indirect ) {
253               next_token( ctx, &inst->Src[i].DimIndirect );
254
255               /*
256               * No support for indirect or multi-dimensional addressing.
257               */
258               assert( !inst->Src[i].Indirect.Indirect );
259               assert( !inst->Src[i].Indirect.Dimension );
260            }
261         }
262      }
263
264      break;
265   }
266
267   case TGSI_TOKEN_TYPE_PROPERTY:
268   {
269      struct tgsi_full_property *prop = &ctx->FullToken.FullProperty;
270      uint prop_count;
271
272      memset(prop, 0, sizeof *prop);
273      copy_token(&prop->Property, &token);
274
275      prop_count = prop->Property.NrTokens - 1;
276      for (i = 0; i < prop_count; i++) {
277         next_token(ctx, &prop->u[i]);
278      }
279
280      break;
281   }
282
283   default:
284      assert( 0 );
285   }
286}
287
288
289
290
291/**
292 * Make a new copy of a token array.
293 */
294struct tgsi_token *
295tgsi_dup_tokens(const struct tgsi_token *tokens)
296{
297   unsigned n = tgsi_num_tokens(tokens);
298   unsigned bytes = n * sizeof(struct tgsi_token);
299   struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes);
300   if (new_tokens)
301      memcpy(new_tokens, tokens, bytes);
302   return new_tokens;
303}
304
305
306/**
307 * Allocate memory for num_tokens tokens.
308 */
309struct tgsi_token *
310tgsi_alloc_tokens(unsigned num_tokens)
311{
312   unsigned bytes = num_tokens * sizeof(struct tgsi_token);
313   return (struct tgsi_token *) MALLOC(bytes);
314}
315
316
317void
318tgsi_dump_tokens(const struct tgsi_token *tokens)
319{
320   const unsigned *dwords = (const unsigned *)tokens;
321   int nr = tgsi_num_tokens(tokens);
322   int i;
323
324   assert(sizeof(*tokens) == sizeof(unsigned));
325
326   debug_printf("const unsigned tokens[%d] = {\n", nr);
327   for (i = 0; i < nr; i++)
328      debug_printf("0x%08x,\n", dwords[i]);
329   debug_printf("};\n");
330}
331