gallium: simplify tgsi tokens further
[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 "util/u_memory.h"
32
33 void
34 tgsi_full_token_init(
35 union tgsi_full_token *full_token )
36 {
37 full_token->Token.Type = TGSI_TOKEN_TYPE_DECLARATION;
38 }
39
40 void
41 tgsi_full_token_free(
42 union tgsi_full_token *full_token )
43 {
44 }
45
46 unsigned
47 tgsi_parse_init(
48 struct tgsi_parse_context *ctx,
49 const struct tgsi_token *tokens )
50 {
51 ctx->FullVersion.Version = *(struct tgsi_version *) &tokens[0];
52 if( ctx->FullVersion.Version.MajorVersion > 1 ) {
53 return TGSI_PARSE_ERROR;
54 }
55
56 ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[1];
57 if( ctx->FullHeader.Header.HeaderSize >= 2 ) {
58 ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[2];
59 }
60 else {
61 return TGSI_PARSE_ERROR;
62 }
63
64 ctx->Tokens = tokens;
65 ctx->Position = 1 + ctx->FullHeader.Header.HeaderSize;
66
67 tgsi_full_token_init( &ctx->FullToken );
68
69 return TGSI_PARSE_OK;
70 }
71
72 void
73 tgsi_parse_free(
74 struct tgsi_parse_context *ctx )
75 {
76 tgsi_full_token_free( &ctx->FullToken );
77 }
78
79 boolean
80 tgsi_parse_end_of_tokens(
81 struct tgsi_parse_context *ctx )
82 {
83 return ctx->Position >=
84 1 + ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize;
85 }
86
87
88 /**
89 * This function is used to avoid and work-around type punning/aliasing
90 * warnings. The warnings seem harmless on x86 but on PPC they cause
91 * real failures.
92 */
93 static INLINE void
94 copy_token(void *dst, const void *src)
95 {
96 memcpy(dst, src, 4);
97 }
98
99
100 /**
101 * Get next 4-byte token, return it at address specified by 'token'
102 */
103 static void
104 next_token(
105 struct tgsi_parse_context *ctx,
106 void *token )
107 {
108 assert( !tgsi_parse_end_of_tokens( ctx ) );
109 copy_token(token, &ctx->Tokens[ctx->Position]);
110 ctx->Position++;
111 }
112
113
114 void
115 tgsi_parse_token(
116 struct tgsi_parse_context *ctx )
117 {
118 struct tgsi_token token;
119 unsigned i;
120
121 tgsi_full_token_free( &ctx->FullToken );
122 tgsi_full_token_init( &ctx->FullToken );
123
124 next_token( ctx, &token );
125
126 switch( token.Type ) {
127 case TGSI_TOKEN_TYPE_DECLARATION:
128 {
129 struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration;
130
131 memset(decl, 0, sizeof *decl);
132 copy_token(&decl->Declaration, &token);
133
134 next_token( ctx, &decl->DeclarationRange );
135
136 if( decl->Declaration.Semantic ) {
137 next_token( ctx, &decl->Semantic );
138 }
139
140 break;
141 }
142
143 case TGSI_TOKEN_TYPE_IMMEDIATE:
144 {
145 struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate;
146
147 memset(imm, 0, sizeof *imm);
148 copy_token(&imm->Immediate, &token);
149
150 switch (imm->Immediate.DataType) {
151 case TGSI_IMM_FLOAT32:
152 {
153 uint imm_count = imm->Immediate.NrTokens - 1;
154 for (i = 0; i < imm_count; i++) {
155 next_token(ctx, &imm->u[i]);
156 }
157 }
158 break;
159
160 default:
161 assert( 0 );
162 }
163
164 break;
165 }
166
167 case TGSI_TOKEN_TYPE_INSTRUCTION:
168 {
169 struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction;
170
171 memset(inst, 0, sizeof *inst);
172 copy_token(&inst->Instruction, &token);
173
174 if (inst->Instruction.Predicate) {
175 next_token(ctx, &inst->InstructionPredicate);
176 }
177
178 if (inst->Instruction.Label) {
179 next_token( ctx, &inst->InstructionLabel);
180 }
181
182 if (inst->Instruction.Texture) {
183 next_token( ctx, &inst->InstructionTexture);
184 }
185
186 assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS );
187
188 for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) {
189
190 next_token( ctx, &inst->FullDstRegisters[i].DstRegister );
191
192 /*
193 * No support for indirect or multi-dimensional addressing.
194 */
195 assert( !inst->FullDstRegisters[i].DstRegister.Dimension );
196
197 if( inst->FullDstRegisters[i].DstRegister.Indirect ) {
198 next_token( ctx, &inst->FullDstRegisters[i].DstRegisterInd );
199
200 /*
201 * No support for indirect or multi-dimensional addressing.
202 */
203 assert( !inst->FullDstRegisters[i].DstRegisterInd.Dimension );
204 assert( !inst->FullDstRegisters[i].DstRegisterInd.Indirect );
205 }
206 }
207
208 assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS );
209
210 for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) {
211
212 next_token( ctx, &inst->FullSrcRegisters[i].SrcRegister );
213
214 if( inst->FullSrcRegisters[i].SrcRegister.Indirect ) {
215 next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterInd );
216
217 /*
218 * No support for indirect or multi-dimensional addressing.
219 */
220 assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Indirect );
221 assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Dimension );
222 }
223
224 if( inst->FullSrcRegisters[i].SrcRegister.Dimension ) {
225 next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterDim );
226
227 /*
228 * No support for multi-dimensional addressing.
229 */
230 assert( !inst->FullSrcRegisters[i].SrcRegisterDim.Dimension );
231
232 if( inst->FullSrcRegisters[i].SrcRegisterDim.Indirect ) {
233 next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterDimInd );
234
235 /*
236 * No support for indirect or multi-dimensional addressing.
237 */
238 assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Indirect );
239 assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Dimension );
240 }
241 }
242 }
243
244 break;
245 }
246
247 default:
248 assert( 0 );
249 }
250 }
251
252
253 unsigned
254 tgsi_num_tokens(const struct tgsi_token *tokens)
255 {
256 struct tgsi_parse_context ctx;
257 if (tgsi_parse_init(&ctx, tokens) == TGSI_PARSE_OK) {
258 unsigned len = (ctx.FullHeader.Header.HeaderSize +
259 ctx.FullHeader.Header.BodySize +
260 1);
261 return len;
262 }
263 return 0;
264 }
265
266
267 /**
268 * Make a new copy of a token array.
269 */
270 struct tgsi_token *
271 tgsi_dup_tokens(const struct tgsi_token *tokens)
272 {
273 unsigned n = tgsi_num_tokens(tokens);
274 unsigned bytes = n * sizeof(struct tgsi_token);
275 struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes);
276 if (new_tokens)
277 memcpy(new_tokens, tokens, bytes);
278 return new_tokens;
279 }