--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "imports.h"
+#include "context.h"
+#include "slang_ir.h"
+#include "prog_print.h"
+
+
+static const slang_ir_info IrInfo[] = {
+ /* binary ops */
+ { IR_ADD, "IR_ADD", OPCODE_ADD, 4, 2 },
+ { IR_SUB, "IR_SUB", OPCODE_SUB, 4, 2 },
+ { IR_MUL, "IR_MUL", OPCODE_MUL, 4, 2 },
+ { IR_DIV, "IR_DIV", OPCODE_NOP, 0, 2 }, /* XXX broke */
+ { IR_DOT4, "IR_DOT_4", OPCODE_DP4, 1, 2 },
+ { IR_DOT3, "IR_DOT_3", OPCODE_DP3, 1, 2 },
+ { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 },
+ { IR_LRP, "IR_LRP", OPCODE_LRP, 4, 3 },
+ { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 },
+ { IR_MAX, "IR_MAX", OPCODE_MAX, 4, 2 },
+ { IR_CLAMP, "IR_CLAMP", OPCODE_NOP, 4, 3 }, /* special case: emit_clamp() */
+ { IR_SEQUAL, "IR_SEQUAL", OPCODE_SEQ, 4, 2 },
+ { IR_SNEQUAL, "IR_SNEQUAL", OPCODE_SNE, 4, 2 },
+ { IR_SGE, "IR_SGE", OPCODE_SGE, 4, 2 },
+ { IR_SGT, "IR_SGT", OPCODE_SGT, 4, 2 },
+ { IR_SLE, "IR_SLE", OPCODE_SLE, 4, 2 },
+ { IR_SLT, "IR_SLT", OPCODE_SLT, 4, 2 },
+ { IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
+ /* unary ops */
+ { IR_I_TO_F, "IR_I_TO_F", OPCODE_NOP, 1, 1 },
+ { IR_F_TO_I, "IR_F_TO_I", OPCODE_INT, 4, 1 }, /* 4 floats to 4 ints */
+ { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 },
+ { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 },
+ { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 },
+ { IR_RSQ, "IR_RSQ", OPCODE_RSQ, 1, 1 },
+ { IR_RCP, "IR_RCP", OPCODE_RCP, 1, 1 },
+ { IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 },
+ { IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 },
+ { IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 },
+ { IR_NEG, "IR_NEG", OPCODE_NOP, 4, 1 }, /* special case: emit_negation() */
+ { IR_DDX, "IR_DDX", OPCODE_DDX, 4, 1 },
+ { IR_DDX, "IR_DDY", OPCODE_DDX, 4, 1 },
+ { IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 },
+ { IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
+ { IR_NOISE1, "IR_NOISE1", OPCODE_NOISE1, 1, 1 },
+ { IR_NOISE2, "IR_NOISE2", OPCODE_NOISE2, 1, 1 },
+ { IR_NOISE3, "IR_NOISE3", OPCODE_NOISE3, 1, 1 },
+ { IR_NOISE4, "IR_NOISE4", OPCODE_NOISE4, 1, 1 },
+
+ /* other */
+ { IR_SEQ, "IR_SEQ", OPCODE_NOP, 0, 0 },
+ { IR_SCOPE, "IR_SCOPE", OPCODE_NOP, 0, 0 },
+ { IR_LABEL, "IR_LABEL", OPCODE_NOP, 0, 0 },
+ { IR_JUMP, "IR_JUMP", OPCODE_NOP, 0, 0 },
+ { IR_IF, "IR_IF", OPCODE_NOP, 0, 0 },
+ { IR_KILL, "IR_KILL", OPCODE_NOP, 0, 0 },
+ { IR_COND, "IR_COND", OPCODE_NOP, 0, 0 },
+ { IR_CALL, "IR_CALL", OPCODE_NOP, 0, 0 },
+ { IR_MOVE, "IR_MOVE", OPCODE_NOP, 0, 1 },
+ { IR_NOT, "IR_NOT", OPCODE_NOP, 1, 1 },
+ { IR_VAR, "IR_VAR", OPCODE_NOP, 0, 0 },
+ { IR_VAR_DECL, "IR_VAR_DECL", OPCODE_NOP, 0, 0 },
+ { IR_TEX, "IR_TEX", OPCODE_TEX, 4, 1 },
+ { IR_TEXB, "IR_TEXB", OPCODE_TXB, 4, 1 },
+ { IR_TEXP, "IR_TEXP", OPCODE_TXP, 4, 1 },
+ { IR_FLOAT, "IR_FLOAT", OPCODE_NOP, 0, 0 }, /* float literal */
+ { IR_FIELD, "IR_FIELD", OPCODE_NOP, 0, 0 },
+ { IR_ELEMENT, "IR_ELEMENT", OPCODE_NOP, 0, 0 },
+ { IR_SWIZZLE, "IR_SWIZZLE", OPCODE_NOP, 0, 0 },
+ { IR_NOP, NULL, OPCODE_NOP, 0, 0 }
+};
+
+
+const slang_ir_info *
+_slang_ir_info(slang_ir_opcode opcode)
+{
+ GLuint i;
+ for (i = 0; IrInfo[i].IrName; i++) {
+ if (IrInfo[i].IrOpcode == opcode) {
+ return IrInfo + i;
+ }
+ }
+ return NULL;
+}
+
+static const char *
+slang_ir_name(slang_ir_opcode opcode)
+{
+ return _slang_ir_info(opcode)->IrName;
+}
+
+
+
+/**
+ * Recursively free an IR tree.
+ */
+void
+_slang_free_ir_tree(slang_ir_node *n)
+{
+#if 1
+ GLuint i;
+ if (!n)
+ return;
+ for (i = 0; i < 3; i++)
+ _slang_free_ir_tree(n->Children[i]);
+ /* Do not free n->List since it's a child elsewhere */
+ free(n);
+#endif
+}
+
+
+
+
+
+
+static const char *
+swizzle_string(GLuint swizzle)
+{
+ static char s[6];
+ GLuint i;
+ s[0] = '.';
+ for (i = 1; i < 5; i++) {
+ s[i] = "xyzw"[GET_SWZ(swizzle, i-1)];
+ }
+ s[i] = 0;
+ return s;
+}
+
+static const char *
+writemask_string(GLuint writemask)
+{
+ static char s[6];
+ GLuint i, j = 0;
+ s[j++] = '.';
+ for (i = 0; i < 4; i++) {
+ if (writemask & (1 << i))
+ s[j++] = "xyzw"[i];
+ }
+ s[j] = 0;
+ return s;
+}
+
+static const char *
+storage_string(const slang_ir_storage *st)
+{
+ static const char *files[] = {
+ "TEMP",
+ "LOCAL_PARAM",
+ "ENV_PARAM",
+ "STATE",
+ "INPUT",
+ "OUTPUT",
+ "NAMED_PARAM",
+ "CONSTANT",
+ "UNIFORM",
+ "WRITE_ONLY",
+ "ADDRESS",
+ "SAMPLER",
+ "UNDEFINED"
+ };
+ static char s[100];
+#if 0
+ if (st->Size == 1)
+ sprintf(s, "%s[%d]", files[st->File], st->Index);
+ else
+ sprintf(s, "%s[%d..%d]", files[st->File], st->Index,
+ st->Index + st->Size - 1);
+#endif
+ assert(st->File < (GLint) (sizeof(files) / sizeof(files[0])));
+ sprintf(s, "%s[%d]", files[st->File], st->Index);
+ return s;
+}
+
+
+static void
+spaces(int n)
+{
+ while (n-- > 0) {
+ printf(" ");
+ }
+}
+
+
+#define IND 0
+
+
+void
+_slang_print_ir_tree(const slang_ir_node *n, int indent)
+{
+ if (!n)
+ return;
+#if !IND
+ if (n->Opcode != IR_SEQ)
+#else
+ printf("%3d:", indent);
+#endif
+ spaces(indent);
+
+ switch (n->Opcode) {
+ case IR_SEQ:
+#if IND
+ printf("SEQ at %p\n", (void*) n);
+#endif
+ assert(n->Children[0]);
+ assert(n->Children[1]);
+ _slang_print_ir_tree(n->Children[0], indent + IND);
+ _slang_print_ir_tree(n->Children[1], indent + IND);
+ break;
+ case IR_SCOPE:
+ printf("NEW SCOPE\n");
+ assert(!n->Children[1]);
+ _slang_print_ir_tree(n->Children[0], indent + 3);
+ break;
+ case IR_MOVE:
+ printf("MOVE (writemask = %s)\n", writemask_string(n->Writemask));
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ _slang_print_ir_tree(n->Children[1], indent+3);
+ break;
+ case IR_LABEL:
+ printf("LABEL: %s\n", n->Label->Name);
+ break;
+ case IR_COND:
+ printf("COND\n");
+ _slang_print_ir_tree(n->Children[0], indent + 3);
+ break;
+ case IR_JUMP:
+ printf("JUMP %s\n", n->Label->Name);
+ break;
+
+ case IR_IF:
+ printf("IF \n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ spaces(indent);
+ printf("THEN\n");
+ _slang_print_ir_tree(n->Children[1], indent+3);
+ if (n->Children[2]) {
+ spaces(indent);
+ printf("ELSE\n");
+ _slang_print_ir_tree(n->Children[2], indent+3);
+ }
+ spaces(indent);
+ printf("ENDIF\n");
+ break;
+
+ case IR_BEGIN_SUB:
+ printf("BEGIN_SUB\n");
+ break;
+ case IR_END_SUB:
+ printf("END_SUB\n");
+ break;
+ case IR_RETURN:
+ printf("RETURN\n");
+ break;
+ case IR_CALL:
+ printf("CALL\n");
+ break;
+
+ case IR_LOOP:
+ printf("LOOP\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ if (n->Children[1]) {
+ spaces(indent);
+ printf("TAIL:\n");
+ _slang_print_ir_tree(n->Children[1], indent+3);
+ }
+ spaces(indent);
+ printf("ENDLOOP\n");
+ break;
+ case IR_CONT:
+ printf("CONT\n");
+ break;
+ case IR_BREAK:
+ printf("BREAK\n");
+ break;
+ case IR_BREAK_IF_FALSE:
+ printf("BREAK_IF_FALSE\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+ case IR_BREAK_IF_TRUE:
+ printf("BREAK_IF_TRUE\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+ case IR_CONT_IF_FALSE:
+ printf("CONT_IF_FALSE\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+ case IR_CONT_IF_TRUE:
+ printf("CONT_IF_TRUE\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+
+ case IR_VAR:
+ printf("VAR %s%s at %s store %p\n",
+ (n->Var ? (char *) n->Var->a_name : "TEMP"),
+ swizzle_string(n->Store->Swizzle),
+ storage_string(n->Store), (void*) n->Store);
+ break;
+ case IR_VAR_DECL:
+ printf("VAR_DECL %s (%p) at %s store %p\n",
+ (n->Var ? (char *) n->Var->a_name : "TEMP"),
+ (void*) n->Var, storage_string(n->Store),
+ (void*) n->Store);
+ break;
+ case IR_FIELD:
+ printf("FIELD %s of\n", n->Field);
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+ case IR_FLOAT:
+ printf("FLOAT %g %g %g %g\n",
+ n->Value[0], n->Value[1], n->Value[2], n->Value[3]);
+ break;
+ case IR_I_TO_F:
+ printf("INT_TO_FLOAT\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+ case IR_F_TO_I:
+ printf("FLOAT_TO_INT\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+ case IR_SWIZZLE:
+ printf("SWIZZLE %s of (store %p) \n",
+ swizzle_string(n->Store->Swizzle), (void*) n->Store);
+ _slang_print_ir_tree(n->Children[0], indent + 3);
+ break;
+ default:
+ printf("%s (%p, %p) (store %p)\n", slang_ir_name(n->Opcode),
+ (void*) n->Children[0], (void*) n->Children[1], (void*) n->Store);
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ _slang_print_ir_tree(n->Children[1], indent+3);
+ }
+}