2 * Mesa 3-D graphics library
4 * Copyright (C) 2005-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 #include "main/imports.h"
27 #include "main/context.h"
29 #include "slang_mem.h"
30 #include "program/prog_instruction.h"
31 #include "program/prog_print.h"
34 static const slang_ir_info IrInfo
[] = {
36 { IR_ADD
, "IR_ADD", OPCODE_ADD
, 4, 2 },
37 { IR_SUB
, "IR_SUB", OPCODE_SUB
, 4, 2 },
38 { IR_MUL
, "IR_MUL", OPCODE_MUL
, 4, 2 },
39 { IR_DIV
, "IR_DIV", OPCODE_NOP
, 0, 2 }, /* XXX broke */
40 { IR_DOT4
, "IR_DOT4", OPCODE_DP4
, 1, 2 },
41 { IR_DOT3
, "IR_DOT3", OPCODE_DP3
, 1, 2 },
42 { IR_DOT2
, "IR_DOT2", OPCODE_DP2
, 1, 2 },
43 { IR_NRM4
, "IR_NRM4", OPCODE_NRM4
, 1, 1 },
44 { IR_NRM3
, "IR_NRM3", OPCODE_NRM3
, 1, 1 },
45 { IR_CROSS
, "IR_CROSS", OPCODE_XPD
, 3, 2 },
46 { IR_LRP
, "IR_LRP", OPCODE_LRP
, 4, 3 },
47 { IR_MIN
, "IR_MIN", OPCODE_MIN
, 4, 2 },
48 { IR_MAX
, "IR_MAX", OPCODE_MAX
, 4, 2 },
49 { IR_CLAMP
, "IR_CLAMP", OPCODE_NOP
, 4, 3 }, /* special case: emit_clamp() */
50 { IR_SEQUAL
, "IR_SEQUAL", OPCODE_SEQ
, 4, 2 },
51 { IR_SNEQUAL
, "IR_SNEQUAL", OPCODE_SNE
, 4, 2 },
52 { IR_SGE
, "IR_SGE", OPCODE_SGE
, 4, 2 },
53 { IR_SGT
, "IR_SGT", OPCODE_SGT
, 4, 2 },
54 { IR_SLE
, "IR_SLE", OPCODE_SLE
, 4, 2 },
55 { IR_SLT
, "IR_SLT", OPCODE_SLT
, 4, 2 },
56 { IR_POW
, "IR_POW", OPCODE_POW
, 1, 2 },
57 { IR_EQUAL
, "IR_EQUAL", OPCODE_NOP
, 1, 2 },
58 { IR_NOTEQUAL
, "IR_NOTEQUAL", OPCODE_NOP
, 1, 2 },
61 { IR_MOVE
, "IR_MOVE", OPCODE_MOV
, 4, 1 },
62 { IR_I_TO_F
, "IR_I_TO_F", OPCODE_MOV
, 4, 1 }, /* int[4] to float[4] */
63 { IR_F_TO_I
, "IR_F_TO_I", OPCODE_TRUNC
, 4, 1 },
64 { IR_EXP
, "IR_EXP", OPCODE_EXP
, 1, 1 },
65 { IR_EXP2
, "IR_EXP2", OPCODE_EX2
, 1, 1 },
66 { IR_LOG2
, "IR_LOG2", OPCODE_LG2
, 1, 1 },
67 { IR_RSQ
, "IR_RSQ", OPCODE_RSQ
, 1, 1 },
68 { IR_RCP
, "IR_RCP", OPCODE_RCP
, 1, 1 },
69 { IR_FLOOR
, "IR_FLOOR", OPCODE_FLR
, 4, 1 },
70 { IR_FRAC
, "IR_FRAC", OPCODE_FRC
, 4, 1 },
71 { IR_ABS
, "IR_ABS", OPCODE_ABS
, 4, 1 },
72 { IR_NEG
, "IR_NEG", OPCODE_NOP
, 4, 1 }, /* special case: emit_negation() */
73 { IR_DDX
, "IR_DDX", OPCODE_DDX
, 4, 1 },
74 { IR_DDY
, "IR_DDY", OPCODE_DDY
, 4, 1 },
75 { IR_SIN
, "IR_SIN", OPCODE_SIN
, 1, 1 },
76 { IR_COS
, "IR_COS", OPCODE_COS
, 1, 1 },
77 { IR_NOISE1
, "IR_NOISE1", OPCODE_NOISE1
, 1, 1 },
78 { IR_NOISE2
, "IR_NOISE2", OPCODE_NOISE2
, 1, 1 },
79 { IR_NOISE3
, "IR_NOISE3", OPCODE_NOISE3
, 1, 1 },
80 { IR_NOISE4
, "IR_NOISE4", OPCODE_NOISE4
, 1, 1 },
83 { IR_CMP
, "IR_CMP", OPCODE_CMP
, 4, 3 }, /* compare/select */
84 { IR_SEQ
, "IR_SEQ", OPCODE_NOP
, 0, 0 },
85 { IR_SCOPE
, "IR_SCOPE", OPCODE_NOP
, 0, 0 },
86 { IR_LABEL
, "IR_LABEL", OPCODE_NOP
, 0, 0 },
87 { IR_IF
, "IR_IF", OPCODE_NOP
, 0, 0 },
88 { IR_KILL
, "IR_KILL", OPCODE_NOP
, 0, 0 },
89 { IR_COND
, "IR_COND", OPCODE_NOP
, 0, 0 },
90 { IR_CALL
, "IR_CALL", OPCODE_NOP
, 0, 0 },
91 { IR_COPY
, "IR_COPY", OPCODE_NOP
, 0, 1 },
92 { IR_NOT
, "IR_NOT", OPCODE_NOP
, 1, 1 },
93 { IR_VAR
, "IR_VAR", OPCODE_NOP
, 0, 0 },
94 { IR_VAR_DECL
, "IR_VAR_DECL", OPCODE_NOP
, 0, 0 },
95 { IR_TEX
, "IR_TEX", OPCODE_TEX
, 4, 1 },
96 { IR_TEXB
, "IR_TEXB", OPCODE_TXB
, 4, 1 },
97 { IR_TEXP
, "IR_TEXP", OPCODE_TXP
, 4, 1 },
98 { IR_TEX_SH
, "IR_TEX_SH", OPCODE_TEX
, 4, 1 },
99 { IR_TEXB_SH
, "IR_TEXB_SH", OPCODE_TXB
, 4, 1 },
100 { IR_TEXP_SH
, "IR_TEXP_SH", OPCODE_TXP
, 4, 1 },
101 { IR_FLOAT
, "IR_FLOAT", OPCODE_NOP
, 0, 0 }, /* float literal */
102 { IR_FIELD
, "IR_FIELD", OPCODE_NOP
, 0, 0 },
103 { IR_ELEMENT
, "IR_ELEMENT", OPCODE_NOP
, 0, 0 },
104 { IR_SWIZZLE
, "IR_SWIZZLE", OPCODE_NOP
, 0, 0 },
105 { IR_NOP
, "IR_NOP", OPCODE_NOP
, 0, 0 },
106 { IR_EMIT_VERTEX
, "IR_EMIT_VERTEX", OPCODE_EMIT_VERTEX
, 0, 0 },
107 { IR_END_PRIMITIVE
, "IR_END_PRIMITIVE", OPCODE_END_PRIMITIVE
, 0, 0 },
112 const slang_ir_info
*
113 _slang_ir_info(slang_ir_opcode opcode
)
116 for (i
= 0; IrInfo
[i
].IrName
; i
++) {
117 if (IrInfo
[i
].IrOpcode
== opcode
) {
126 _slang_init_ir_storage(slang_ir_storage
*st
,
127 gl_register_file file
, GLint index
, GLint size
,
133 st
->Swizzle
= swizzle
;
135 st
->IsIndirect
= GL_FALSE
;
142 * Return a new slang_ir_storage object.
145 _slang_new_ir_storage(gl_register_file file
, GLint index
, GLint size
)
147 slang_ir_storage
*st
;
148 st
= (slang_ir_storage
*) _slang_alloc(sizeof(slang_ir_storage
));
153 st
->Swizzle
= SWIZZLE_NOOP
;
155 st
->IsIndirect
= GL_FALSE
;
164 * Return a new slang_ir_storage object.
167 _slang_new_ir_storage_swz(gl_register_file file
, GLint index
, GLint size
,
170 slang_ir_storage
*st
;
171 st
= (slang_ir_storage
*) _slang_alloc(sizeof(slang_ir_storage
));
176 st
->Swizzle
= swizzle
;
178 st
->IsIndirect
= GL_FALSE
;
186 * Return a new slang_ir_storage object.
189 _slang_new_ir_storage_2d(gl_register_file file
,
190 GLint index
, GLint index2
,
191 GLint size
, GLuint swizzle
)
193 slang_ir_storage
*st
;
194 st
= (slang_ir_storage
*) _slang_alloc(sizeof(slang_ir_storage
));
199 st
->Swizzle
= swizzle
;
201 st
->IsIndirect
= GL_FALSE
;
211 * Return a new slang_ir_storage object.
214 _slang_new_ir_storage_relative(GLint index
, GLint size
,
215 slang_ir_storage
*parent
)
217 slang_ir_storage
*st
;
218 st
= (slang_ir_storage
*) _slang_alloc(sizeof(slang_ir_storage
));
220 st
->File
= PROGRAM_UNDEFINED
;
223 st
->Swizzle
= SWIZZLE_NOOP
;
225 st
->IsIndirect
= GL_FALSE
;
234 _slang_new_ir_storage_indirect(gl_register_file file
,
237 gl_register_file indirectFile
,
239 GLuint indirectSwizzle
)
241 slang_ir_storage
*st
;
242 st
= (slang_ir_storage
*) _slang_alloc(sizeof(slang_ir_storage
));
247 st
->Swizzle
= SWIZZLE_NOOP
;
248 st
->IsIndirect
= GL_TRUE
;
249 st
->IndirectFile
= indirectFile
;
250 st
->IndirectIndex
= indirectIndex
;
251 st
->IndirectSwizzle
= indirectSwizzle
;
260 * Allocate IR storage for a texture sampler.
261 * \param sampNum the sampler number/index
262 * \param texTarget one of TEXTURE_x_INDEX values
263 * \param size number of samplers (in case of sampler array)
266 _slang_new_ir_storage_sampler(GLint sampNum
, GLuint texTarget
, GLint size
)
268 slang_ir_storage
*st
;
269 assert(texTarget
< NUM_TEXTURE_TARGETS
);
270 st
= _slang_new_ir_storage(PROGRAM_SAMPLER
, sampNum
, size
);
272 st
->TexTarget
= texTarget
;
279 /* XXX temporary function */
281 _slang_copy_ir_storage(slang_ir_storage
*dst
, const slang_ir_storage
*src
)
290 _slang_ir_name(slang_ir_opcode opcode
)
292 return _slang_ir_info(opcode
)->IrName
;
297 #if 0 /* no longer needed with mempool */
299 * Since many IR nodes might point to the same IR storage info, we need
300 * to be careful when deleting things.
301 * Before deleting an IR tree, traverse it and do refcounting on the
302 * IR storage nodes. Use the refcount info during delete to free things
306 _slang_refcount_storage(slang_ir_node
*n
)
312 n
->Store
->RefCount
++;
313 for (i
= 0; i
< 3; i
++)
314 _slang_refcount_storage(n
->Children
[i
]);
320 _slang_free_ir(slang_ir_node
*n
)
328 n
->Store
->RefCount
--;
329 if (n
->Store
->RefCount
== 0) {
330 _slang_free(n
->Store
);
336 for (i
= 0; i
< 3; i
++)
337 _slang_free_ir(n
->Children
[i
]);
338 /* Do not free n->List since it's a child elsewhere */
344 * Recursively free an IR tree.
347 _slang_free_ir_tree(slang_ir_node
*n
)
350 _slang_refcount_storage(n
);
357 storage_string(const slang_ir_storage
*st
)
359 static const char *files
[] = {
376 assert(Elements(files
) == PROGRAM_FILE_MAX
);
379 _mesa_snprintf(s
, "%s[%d]", files
[st
->File
], st
->Index
);
381 _mesa_snprintf(s
, "%s[%d..%d]", files
[st
->File
], st
->Index
,
382 st
->Index
+ st
->Size
- 1);
384 assert(st
->File
< (GLint
) (sizeof(files
) / sizeof(files
[0])));
385 _mesa_snprintf(s
, sizeof(s
), "%s[%d]", files
[st
->File
], st
->Index
);
400 _slang_print_ir_tree(const slang_ir_node
*n
, int indent
)
407 if (n
->Opcode
!= IR_SEQ
)
409 printf("%3d:", indent
);
416 printf("SEQ at %p\n", (void*) n
);
418 assert(n
->Children
[0]);
419 assert(n
->Children
[1]);
420 _slang_print_ir_tree(n
->Children
[0], indent
+ IND
);
421 _slang_print_ir_tree(n
->Children
[1], indent
+ IND
);
424 printf("NEW SCOPE\n");
425 assert(!n
->Children
[1]);
426 _slang_print_ir_tree(n
->Children
[0], indent
+ 3);
430 _slang_print_ir_tree(n
->Children
[0], indent
+3);
431 _slang_print_ir_tree(n
->Children
[1], indent
+3);
434 printf("LABEL: %s\n", n
->Label
->Name
);
438 _slang_print_ir_tree(n
->Children
[0], indent
+ 3);
443 _slang_print_ir_tree(n
->Children
[0], indent
+3);
446 _slang_print_ir_tree(n
->Children
[1], indent
+3);
447 if (n
->Children
[2]) {
450 _slang_print_ir_tree(n
->Children
[2], indent
+3);
457 printf("BEGIN_SUB\n");
466 printf("CALL %s\n", n
->Label
->Name
);
471 _slang_print_ir_tree(n
->Children
[0], indent
+3);
472 if (n
->Children
[1]) {
475 _slang_print_ir_tree(n
->Children
[1], indent
+3);
486 case IR_BREAK_IF_TRUE
:
487 printf("BREAK_IF_TRUE\n");
488 _slang_print_ir_tree(n
->Children
[0], indent
+3);
490 case IR_CONT_IF_TRUE
:
491 printf("CONT_IF_TRUE\n");
492 _slang_print_ir_tree(n
->Children
[0], indent
+3);
496 printf("VAR %s%s at %s store %p\n",
497 (n
->Var
? (char *) n
->Var
->a_name
: "TEMP"),
498 _mesa_swizzle_string(n
->Store
->Swizzle
, 0, 0),
499 storage_string(n
->Store
), (void*) n
->Store
);
502 printf("VAR_DECL %s (%p) at %s store %p\n",
503 (n
->Var
? (char *) n
->Var
->a_name
: "TEMP"),
504 (void*) n
->Var
, storage_string(n
->Store
),
508 printf("FIELD %s of\n", n
->Field
);
509 _slang_print_ir_tree(n
->Children
[0], indent
+3);
512 printf("FLOAT %g %g %g %g\n",
513 n
->Value
[0], n
->Value
[1], n
->Value
[2], n
->Value
[3]);
516 printf("INT_TO_FLOAT\n");
517 _slang_print_ir_tree(n
->Children
[0], indent
+3);
520 printf("FLOAT_TO_INT\n");
521 _slang_print_ir_tree(n
->Children
[0], indent
+3);
524 printf("SWIZZLE %s of (store %p) \n",
525 _mesa_swizzle_string(n
->Store
->Swizzle
, 0, 0), (void*) n
->Store
);
526 _slang_print_ir_tree(n
->Children
[0], indent
+ 3);
529 printf("%s (%p, %p) (store %p)\n", _slang_ir_name(n
->Opcode
),
530 (void*) n
->Children
[0], (void*) n
->Children
[1], (void*) n
->Store
);
531 _slang_print_ir_tree(n
->Children
[0], indent
+3);
532 _slang_print_ir_tree(n
->Children
[1], indent
+3);