Move storage allocation functions from slang_emit.c to slang_codegen.c
[mesa.git] / src / mesa / shader / slang / slang_emit.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
4 *
5 * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file slang_emit.c
27 * Emit program instructions (PI code) from IR trees.
28 * \author Brian Paul
29 */
30
31 #include "imports.h"
32 #include "context.h"
33 #include "macros.h"
34 #include "program.h"
35 #include "prog_instruction.h"
36 #include "prog_parameter.h"
37 #include "slang_emit.h"
38
39
40 /**
41 * Assembly and IR info
42 */
43 typedef struct
44 {
45 slang_ir_opcode IrOpcode;
46 const char *IrName;
47 gl_inst_opcode InstOpcode;
48 GLuint ResultSize, NumParams;
49 } slang_ir_info;
50
51
52
53 static slang_ir_info IrInfo[] = {
54 /* binary ops */
55 { IR_ADD, "IR_ADD", OPCODE_ADD, 4, 2 },
56 { IR_SUB, "IR_SUB", OPCODE_SUB, 4, 2 },
57 { IR_MUL, "IR_MUL", OPCODE_MUL, 4, 2 },
58 { IR_DIV, "IR_DIV", OPCODE_NOP, 0, 2 }, /* XXX broke */
59 { IR_DOT4, "IR_DOT_4", OPCODE_DP4, 1, 2 },
60 { IR_DOT3, "IR_DOT_3", OPCODE_DP3, 1, 2 },
61 { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 },
62 { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 },
63 { IR_MAX, "IR_MAX", OPCODE_MAX, 4, 2 },
64 { IR_SEQUAL, "IR_SEQUAL", OPCODE_SEQ, 4, 2 },
65 { IR_SNEQUAL, "IR_SNEQUAL", OPCODE_SNE, 4, 2 },
66 { IR_SGE, "IR_SGE", OPCODE_SGE, 4, 2 },
67 { IR_SGT, "IR_SGT", OPCODE_SGT, 4, 2 },
68 { IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
69 /* unary ops */
70 { IR_I_TO_F, "IR_I_TO_F", OPCODE_NOP, 1, 1 },
71 { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 },
72 { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 },
73 { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 },
74 { IR_RSQ, "IR_RSQ", OPCODE_RSQ, 1, 1 },
75 { IR_RCP, "IR_RCP", OPCODE_RCP, 1, 1 },
76 { IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 },
77 { IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 },
78 { IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 },
79 { IR_NEG, "IR_NEG", 0/*spec case*/, 4, 1 },
80 { IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 },
81 { IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
82 /* other */
83 { IR_SEQ, "IR_SEQ", 0, 0, 0 },
84 { IR_LABEL, "IR_LABEL", 0, 0, 0 },
85 { IR_JUMP, "IR_JUMP", 0, 0, 0 },
86 { IR_CJUMP, "IR_CJUMP", 0, 0, 0 },
87 { IR_COND, "IR_COND", 0, 0, 0 },
88 { IR_CALL, "IR_CALL", 0, 0, 0 },
89 { IR_MOVE, "IR_MOVE", 0, 0, 1 },
90 { IR_NOT, "IR_NOT", 0, 1, 1 },
91 { IR_VAR, "IR_VAR", 0, 0, 0 },
92 { IR_VAR_DECL, "IR_VAR_DECL", 0, 0, 0 },
93 { IR_TEX, "IR_TEX", OPCODE_TEX, 4, 1 },
94 { IR_TEXB, "IR_TEXB", OPCODE_TXB, 4, 2 },
95 { IR_FLOAT, "IR_FLOAT", 0, 0, 0 },
96 { IR_FIELD, "IR_FIELD", 0, 0, 0 },
97 { IR_NOP, NULL, OPCODE_NOP, 0, 0 }
98 };
99
100
101 static slang_ir_info *
102 slang_find_ir_info(slang_ir_opcode opcode)
103 {
104 GLuint i;
105 for (i = 0; IrInfo[i].IrName; i++) {
106 if (IrInfo[i].IrOpcode == opcode) {
107 return IrInfo + i;
108 }
109 }
110 return NULL;
111 }
112
113 static const char *
114 slang_ir_name(slang_ir_opcode opcode)
115 {
116 return slang_find_ir_info(opcode)->IrName;
117 }
118
119
120 slang_ir_storage *
121 _slang_new_ir_storage(enum register_file file, GLint index, GLint size)
122 {
123 slang_ir_storage *st;
124 st = (slang_ir_storage *) _mesa_calloc(sizeof(slang_ir_storage));
125 if (st) {
126 st->File = file;
127 st->Index = index;
128 st->Size = size;
129 }
130 return st;
131 }
132
133
134 slang_ir_storage *
135 _slang_clone_ir_storage(slang_ir_storage *store)
136 {
137 slang_ir_storage *clone
138 = _slang_new_ir_storage(store->File, store->Index, store->Size);
139 return clone;
140 }
141
142
143 static const char *
144 swizzle_string(GLuint swizzle)
145 {
146 static char s[6];
147 GLuint i;
148 s[0] = '.';
149 for (i = 1; i < 5; i++) {
150 s[i] = "xyzw"[GET_SWZ(swizzle, i-1)];
151 }
152 s[i] = 0;
153 return s;
154 }
155
156 static const char *
157 writemask_string(GLuint writemask)
158 {
159 static char s[6];
160 GLuint i, j = 0;
161 s[j++] = '.';
162 for (i = 0; i < 4; i++) {
163 if (writemask & (1 << i))
164 s[j++] = "xyzw"[i];
165 }
166 s[j] = 0;
167 return s;
168 }
169
170 static const char *
171 storage_string(const slang_ir_storage *st)
172 {
173 static const char *files[] = {
174 "TEMP",
175 "LOCAL_PARAM",
176 "ENV_PARAM",
177 "STATE",
178 "INPUT",
179 "OUTPUT",
180 "NAMED_PARAM",
181 "CONSTANT",
182 "UNIFORM",
183 "WRITE_ONLY",
184 "ADDRESS",
185 "SAMPLER",
186 "UNDEFINED"
187 };
188 static char s[100];
189 #if 0
190 if (st->Size == 1)
191 sprintf(s, "%s[%d]", files[st->File], st->Index);
192 else
193 sprintf(s, "%s[%d..%d]", files[st->File], st->Index,
194 st->Index + st->Size - 1);
195 #endif
196 assert(st->File < sizeof(files) / sizeof(files[0]));
197 sprintf(s, "%s[%d]", files[st->File], st->Index);
198 return s;
199 }
200
201
202 #define IND 0
203 void
204 slang_print_ir(const slang_ir_node *n, int indent)
205 {
206 int i;
207 if (!n)
208 return;
209 #if !IND
210 if (n->Opcode != IR_SEQ)
211 #else
212 printf("%3d:", indent);
213 #endif
214 for (i = 0; i < indent; i++)
215 printf(" ");
216
217 switch (n->Opcode) {
218 case IR_SEQ:
219 #if IND
220 printf("SEQ at %p\n", (void*) n);
221 #endif
222 assert(n->Children[0]);
223 assert(n->Children[1]);
224 slang_print_ir(n->Children[0], indent + IND);
225 slang_print_ir(n->Children[1], indent + IND);
226 break;
227 case IR_MOVE:
228 printf("MOVE (writemask = %s)\n", writemask_string(n->Writemask));
229 slang_print_ir(n->Children[0], indent+3);
230 slang_print_ir(n->Children[1], indent+3);
231 break;
232 case IR_LABEL:
233 printf("LABEL: %s\n", n->Target);
234 break;
235 case IR_COND:
236 printf("COND\n");
237 slang_print_ir(n->Children[0], indent + 3);
238 break;
239 case IR_JUMP:
240 printf("JUMP %s\n", n->Target);
241 break;
242 case IR_CJUMP:
243 printf("CJUMP %s\n", n->Target);
244 slang_print_ir(n->Children[0], indent+3);
245 break;
246 case IR_VAR:
247 printf("VAR %s%s at %s store %p\n",
248 (char *) n->Var->a_name, swizzle_string(n->Swizzle),
249 storage_string(n->Store), (void*) n->Store);
250 break;
251 case IR_VAR_DECL:
252 printf("VAR_DECL %s (%p) at %s store %p\n",
253 (char *) n->Var->a_name, (void*) n->Var, storage_string(n->Store),
254 (void*) n->Store);
255 break;
256 case IR_FIELD:
257 printf("FIELD %s of\n", n->Target);
258 slang_print_ir(n->Children[0], indent+3);
259 break;
260 case IR_CALL:
261 printf("ASMCALL %s(%d args)\n", n->Target, n->Swizzle);
262 break;
263 case IR_FLOAT:
264 printf("FLOAT %f %f %f %f\n",
265 n->Value[0], n->Value[1], n->Value[2], n->Value[3]);
266 break;
267 case IR_I_TO_F:
268 printf("INT_TO_FLOAT %d\n", (int) n->Value[0]);
269 break;
270 default:
271 printf("%s (%p, %p)\n", slang_ir_name(n->Opcode),
272 (void*) n->Children[0], (void*) n->Children[1]);
273 slang_print_ir(n->Children[0], indent+3);
274 slang_print_ir(n->Children[1], indent+3);
275 }
276 }
277
278
279 GLint
280 _slang_alloc_temporary(slang_gen_context *gc, GLint size)
281 {
282 const GLuint sz4 = (size + 3) / 4;
283 GLuint i, j;
284 ASSERT(size > 0); /* number of floats */
285 for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
286 GLuint found = 0;
287 for (j = 0; j < sz4; j++) {
288 if (!gc->TempUsed[i + j]) {
289 found++;
290 }
291 }
292 if (found == sz4) {
293 /* found block of size/4 free regs */
294 for (j = 0; j < sz4; j++)
295 gc->TempUsed[i + j] = GL_TRUE;
296 return i;
297 }
298 }
299 return -1;
300 }
301
302
303
304 static GLboolean
305 is_temporary(const slang_gen_context *gc, const slang_ir_storage *st)
306 {
307 if (st->File == PROGRAM_TEMPORARY && gc->TempUsed[st->Index])
308 return gc->TempUsed[st->Index];
309 else
310 return GL_FALSE;
311 }
312
313
314 static void
315 free_temporary(slang_gen_context *gc, GLuint r, GLint size)
316 {
317 const GLuint sz4 = (size + 3) / 4;
318 GLuint i;
319 for (i = 0; i < sz4; i++) {
320 if (gc->TempUsed[r + i])
321 gc->TempUsed[r + i] = GL_FALSE;
322 }
323 }
324
325
326 /**
327 * Allocate temporary storage for an intermediate result (such as for
328 * a multiply or add, etc.
329 */
330 static void
331 slang_alloc_temp_storage(slang_gen_context *gc, slang_ir_node *n, GLint size)
332 {
333 GLint indx;
334 assert(!n->Var);
335 assert(!n->Store);
336 assert(size > 0);
337 indx = _slang_alloc_temporary(gc, size);
338 n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, indx, size);
339 }
340
341
342 static slang_ir_storage *
343 alloc_constant(const GLfloat v[], GLuint size, struct gl_program *prog)
344 {
345 GLuint swizzle;
346 GLint ind = _mesa_add_unnamed_constant(prog->Parameters, v, size, &swizzle);
347 slang_ir_storage *st = _slang_new_ir_storage(PROGRAM_CONSTANT, ind, size);
348 return st;
349 }
350
351
352 /**
353 * Swizzle a swizzle.
354 */
355 #if 0
356 static GLuint
357 swizzle_compose(GLuint swz1, GLuint swz2)
358 {
359 GLuint i, swz, s[4];
360 for (i = 0; i < 4; i++) {
361 GLuint c = GET_SWZ(swz1, i);
362 s[i] = GET_SWZ(swz2, c);
363 }
364 swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]);
365 return swz;
366 }
367 #endif
368
369
370 /**
371 * Convert IR storage to an instruction dst register.
372 */
373 static void
374 storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,
375 GLuint writemask)
376 {
377 static const GLuint defaultWritemask[4] = {
378 WRITEMASK_X,
379 WRITEMASK_X | WRITEMASK_Y,
380 WRITEMASK_X | WRITEMASK_Y | WRITEMASK_Z,
381 WRITEMASK_X | WRITEMASK_Y | WRITEMASK_Z | WRITEMASK_W
382 };
383 dst->File = st->File;
384 dst->Index = st->Index;
385 assert(st->File != PROGRAM_UNDEFINED);
386 assert(st->Size >= 1);
387 assert(st->Size <= 4);
388 dst->WriteMask = defaultWritemask[st->Size - 1] & writemask;
389 }
390
391
392 /**
393 * Convert IR storage to an instruction src register.
394 */
395 static void
396 storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st,
397 GLuint swizzle)
398 {
399 static const GLuint defaultSwizzle[4] = {
400 MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
401 MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
402 MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
403 MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W)
404 };
405
406 src->File = st->File;
407 src->Index = st->Index;
408 assert(st->File != PROGRAM_UNDEFINED);
409 assert(st->Size >= 1);
410 assert(st->Size <= 4);
411 /* XXX swizzling logic here may need some work */
412 /*src->Swizzle = swizzle_compose(swizzle, defaultSwizzle[st->Size - 1]);*/
413 if (swizzle != SWIZZLE_NOOP)
414 src->Swizzle = swizzle;
415 else
416 src->Swizzle = defaultSwizzle[st->Size - 1];
417 }
418
419
420
421 /**
422 * Add new instruction at end of given program.
423 * \param prog the program to append instruction onto
424 * \param opcode opcode for the new instruction
425 * \return pointer to the new instruction
426 */
427 static struct prog_instruction *
428 new_instruction(struct gl_program *prog, gl_inst_opcode opcode)
429 {
430 struct prog_instruction *inst;
431 prog->Instructions = _mesa_realloc_instructions(prog->Instructions,
432 prog->NumInstructions,
433 prog->NumInstructions + 1);
434 inst = prog->Instructions + prog->NumInstructions;
435 prog->NumInstructions++;
436 _mesa_init_instructions(inst, 1);
437 inst->Opcode = opcode;
438 return inst;
439 }
440
441
442 static struct prog_instruction *
443 emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog);
444
445
446 /**
447 * Generate code for a simple binary-op instruction.
448 */
449 static struct prog_instruction *
450 emit_binop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
451 {
452 struct prog_instruction *inst;
453 const slang_ir_info *info = slang_find_ir_info(n->Opcode);
454 assert(info);
455
456 assert(info->InstOpcode != OPCODE_NOP);
457
458 emit(gc, n->Children[0], prog);
459 emit(gc, n->Children[1], prog);
460 inst = new_instruction(prog, info->InstOpcode);
461 /* alloc temp storage for the result: */
462 if (!n->Store || n->Store->File == PROGRAM_UNDEFINED) {
463 slang_alloc_temp_storage(gc, n, info->ResultSize);
464 }
465 storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
466 storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
467 n->Children[0]->Swizzle);
468 storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store,
469 n->Children[1]->Swizzle);
470 inst->Comment = n->Comment;
471 return inst;
472 }
473
474
475 static struct prog_instruction *
476 emit_unop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
477 {
478 struct prog_instruction *inst;
479 const slang_ir_info *info = slang_find_ir_info(n->Opcode);
480 assert(info);
481
482 assert(info->NumParams == 1);
483
484 emit(gc, n->Children[0], prog);
485
486 inst = new_instruction(prog, info->InstOpcode);
487
488 if (!n->Store)
489 slang_alloc_temp_storage(gc, n, info->ResultSize);
490
491 storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
492
493 storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
494 n->Children[0]->Swizzle);
495
496 inst->Comment = n->Comment;
497
498 return inst;
499 }
500
501
502 static struct prog_instruction *
503 emit_negation(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
504 {
505 /* Implement as MOV dst, -src; */
506 /* XXX we could look at the previous instruction and in some circumstances
507 * modify it to accomplish the negation.
508 */
509 struct prog_instruction *inst;
510
511 emit(gc, n->Children[0], prog);
512
513 if (!n->Store)
514 slang_alloc_temp_storage(gc, n, n->Children[0]->Store->Size);
515
516 inst = new_instruction(prog, OPCODE_MOV);
517 storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
518 storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
519 n->Children[0]->Swizzle);
520 inst->SrcReg[0].NegateBase = NEGATE_XYZW;
521 inst->Comment = n->Comment;
522 return inst;
523 }
524
525
526 static struct prog_instruction *
527 emit_label(const char *target, struct gl_program *prog)
528 {
529 struct prog_instruction *inst;
530 inst = new_instruction(prog, OPCODE_NOP);
531 inst->Comment = _mesa_strdup(target);
532 return inst;
533 }
534
535
536 static struct prog_instruction *
537 emit_cjump(const char *target, struct gl_program *prog)
538 {
539 struct prog_instruction *inst;
540 inst = new_instruction(prog, OPCODE_BRA);
541 inst->DstReg.CondMask = COND_EQ; /* branch if equal to zero */
542 inst->DstReg.CondSwizzle = SWIZZLE_X;
543 inst->Comment = _mesa_strdup(target);
544 return inst;
545 }
546
547
548 static struct prog_instruction *
549 emit_jump(const char *target, struct gl_program *prog)
550 {
551 struct prog_instruction *inst;
552 inst = new_instruction(prog, OPCODE_BRA);
553 inst->DstReg.CondMask = COND_TR; /* always branch */
554 /*inst->DstReg.CondSwizzle = SWIZZLE_X;*/
555 inst->Comment = _mesa_strdup(target);
556 return inst;
557 }
558
559
560 static struct prog_instruction *
561 emit_tex(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
562 {
563 struct prog_instruction *inst;
564 if (n->Opcode == IR_TEX) {
565 inst = new_instruction(prog, OPCODE_TEX);
566 }
567 else {
568 assert(n->Opcode == IR_TEXB);
569 inst = new_instruction(prog, OPCODE_TXB);
570 }
571
572 if (!n->Store)
573 slang_alloc_temp_storage(gc, n, 4);
574
575 storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
576
577 /* Child[1] is the coord */
578 storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store,
579 n->Children[1]->Swizzle);
580
581 /* Child[0] is the sampler (a uniform which'll indicate the texture unit) */
582 assert(n->Children[0]->Store);
583 assert(n->Children[0]->Store->Size >= TEXTURE_1D_INDEX);
584
585 inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */
586 inst->TexSrcTarget = n->Children[0]->Store->Size;
587 inst->TexSrcUnit = 27; /* Dummy value; the TexSrcUnit will be computed at
588 * link time, using the sampler uniform's value.
589 */
590 return inst;
591 }
592
593
594 static struct prog_instruction *
595 emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
596 {
597 struct prog_instruction *inst;
598 if (!n)
599 return NULL;
600
601 switch (n->Opcode) {
602 case IR_SEQ:
603 assert(n->Children[0]);
604 assert(n->Children[1]);
605 emit(gc, n->Children[0], prog);
606 inst = emit(gc, n->Children[1], prog);
607 n->Store = n->Children[1]->Store;
608 return inst;
609 break;
610 case IR_VAR_DECL:
611 case IR_VAR:
612 /* Storage should have already been resolved/allocated */
613 assert(n->Store);
614 assert(n->Store->File != PROGRAM_UNDEFINED);
615 assert(n->Store->Index >= 0);
616 assert(n->Store->Size > 0);
617 break;
618 case IR_MOVE:
619 /* rhs */
620 assert(n->Children[1]);
621 inst = emit(gc, n->Children[1], prog);
622 /* lhs */
623 emit(gc, n->Children[0], prog);
624
625 #if 1
626 if (inst && is_temporary(gc, n->Children[1]->Store)) {
627 /* Peephole optimization:
628 * Just modify the RHS to put its result into the dest of this
629 * MOVE operation. Then, this MOVE is a no-op.
630 */
631 free_temporary(gc, n->Children[1]->Store->Index,
632 n->Children[1]->Store->Size);
633 *n->Children[1]->Store = *n->Children[0]->Store;
634 /* fixup the prev (RHS) instruction */
635 storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
636 return inst;
637 }
638 else
639 #endif
640 {
641 if (n->Children[0]->Store->Size > 4) {
642 /* move matrix/struct etc */
643 slang_ir_storage dstStore = *n->Children[0]->Store;
644 slang_ir_storage srcStore = *n->Children[1]->Store;
645 GLint size = srcStore.Size;
646 ASSERT(n->Children[0]->Writemask == WRITEMASK_XYZW);
647 ASSERT(n->Children[1]->Swizzle == SWIZZLE_NOOP);
648 dstStore.Size = 4;
649 srcStore.Size = 4;
650 while (size >= 4) {
651 inst = new_instruction(prog, OPCODE_MOV);
652 inst->Comment = _mesa_strdup("IR_MOVE block");
653 storage_to_dst_reg(&inst->DstReg, &dstStore, n->Writemask);
654 storage_to_src_reg(&inst->SrcReg[0], &srcStore,
655 n->Children[1]->Swizzle);
656 srcStore.Index++;
657 dstStore.Index++;
658 size -= 4;
659 }
660 }
661 else {
662 inst = new_instruction(prog, OPCODE_MOV);
663 storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
664 storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store,
665 n->Children[1]->Swizzle);
666 }
667 /* XXX is this test correct? */
668 if (n->Children[1]->Store->File == PROGRAM_TEMPORARY) {
669 free_temporary(gc, n->Children[1]->Store->Index,
670 n->Children[1]->Store->Size);
671 }
672 /*inst->Comment = _mesa_strdup("IR_MOVE");*/
673 n->Store = n->Children[0]->Store; /*XXX new */
674 return inst;
675 }
676 break;
677 case IR_ADD:
678 case IR_SUB:
679 case IR_MUL:
680 case IR_DOT4:
681 case IR_DOT3:
682 case IR_CROSS:
683 case IR_MIN:
684 case IR_MAX:
685 case IR_SEQUAL:
686 case IR_SNEQUAL:
687 case IR_SGE:
688 case IR_SGT:
689 case IR_POW:
690 case IR_EXP:
691 case IR_EXP2:
692 return emit_binop(gc, n, prog);
693 case IR_RSQ:
694 case IR_RCP:
695 case IR_FLOOR:
696 case IR_FRAC:
697 case IR_ABS:
698 case IR_SIN:
699 case IR_COS:
700 return emit_unop(gc, n, prog);
701 case IR_TEX:
702 case IR_TEXB:
703 return emit_tex(gc, n, prog);
704 case IR_NEG:
705 return emit_negation(gc, n, prog);
706 case IR_LABEL:
707 return emit_label(n->Target, prog);
708 case IR_FLOAT:
709 n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */
710 break;
711 case IR_COND:
712 {
713 /* Conditional expression (in if/while/for stmts).
714 * Need to update condition code register.
715 * Next instruction is typically an IR_CJUMP.
716 */
717 /* last child expr instruction: */
718 struct prog_instruction *inst = emit(gc, n->Children[0], prog);
719 if (inst) {
720 /* set inst's CondUpdate flag */
721 inst->CondUpdate = GL_TRUE;
722 return inst; /* XXX or null? */
723 }
724 else {
725 /* This'll happen for things like "if (i) ..." where no code
726 * is normally generated for the expression "i".
727 * Generate a move instruction just to set condition codes.
728 */
729 slang_alloc_temp_storage(gc, n, 1);
730 inst = new_instruction(prog, OPCODE_MOV);
731 inst->CondUpdate = GL_TRUE;
732 storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
733 storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
734 n->Children[0]->Swizzle);
735 free_temporary(gc, n->Store->Index, n->Store->Size);
736 return inst; /* XXX or null? */
737 }
738 }
739 return NULL;
740 case IR_JUMP:
741 return emit_jump(n->Target, prog);
742 case IR_CJUMP:
743 return emit_cjump(n->Target, prog);
744 default:
745 printf("emit: ?\n");
746 abort();
747 }
748 return NULL;
749 }
750
751
752 slang_gen_context *
753 _slang_new_codegen_context(void)
754 {
755 slang_gen_context *gc = (slang_gen_context *) _mesa_calloc(sizeof(*gc));
756 return gc;
757 }
758
759
760
761 GLboolean
762 _slang_emit_code(slang_ir_node *n, slang_gen_context *gc,
763 struct gl_program *prog)
764 {
765 /*GET_CURRENT_CONTEXT(ctx);*/
766
767 /*
768 gc = _slang_new_codegen_context();
769 */
770
771 printf("************ Begin generate code\n");
772
773 (void) emit(gc, n, prog);
774
775 {
776 struct prog_instruction *inst;
777 inst = new_instruction(prog, OPCODE_END);
778 }
779
780 printf("************ End generate code (%u inst):\n", prog->NumInstructions);
781
782 #if 0
783 _mesa_print_program(prog);
784 _mesa_print_program_parameters(ctx,prog);
785 #endif
786
787 _mesa_free(gc);
788
789 return GL_FALSE;
790 }