Merge branch 'mesa_7_6_branch'
[mesa.git] / src / mesa / shader / slang / slang_ir.c
index dd17b4a1e0b35136516e36a1ae8b48f2ecfacc5a..62603503dd9ad32d4a278dc4d3d83210e970d7ed 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.3
  *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2009  VMware, Inc.   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"),
  */
 
 
-#include "imports.h"
-#include "context.h"
+#include "main/imports.h"
+#include "main/context.h"
 #include "slang_ir.h"
-#include "prog_print.h"
+#include "slang_mem.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_print.h"
 
 
 static const slang_ir_info IrInfo[] = {
@@ -35,8 +37,11 @@ static const slang_ir_info IrInfo[] = {
    { 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_DOT4, "IR_DOT4", OPCODE_DP4, 1, 2 },
+   { IR_DOT3, "IR_DOT3", OPCODE_DP3, 1, 2 },
+   { IR_DOT2, "IR_DOT2", OPCODE_DP2, 1, 2 },
+   { IR_NRM4, "IR_NRM4", OPCODE_NRM4, 1, 1 },
+   { IR_NRM3, "IR_NRM3", OPCODE_NRM3, 1, 1 },
    { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 },
    { IR_LRP, "IR_LRP", OPCODE_LRP, 4, 3 },
    { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 },
@@ -49,9 +54,13 @@ static const slang_ir_info IrInfo[] = {
    { IR_SLE, "IR_SLE", OPCODE_SLE, 4, 2 },
    { IR_SLT, "IR_SLT", OPCODE_SLT, 4, 2 },
    { IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
+   { IR_EQUAL, "IR_EQUAL", OPCODE_NOP, 1, 2 },
+   { IR_NOTEQUAL, "IR_NOTEQUAL", OPCODE_NOP, 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_MOVE, "IR_MOVE", OPCODE_MOV, 4, 1 },
+   { IR_I_TO_F, "IR_I_TO_F", OPCODE_MOV, 4, 1 },  /* int[4] to float[4] */
+   { IR_F_TO_I, "IR_F_TO_I", OPCODE_TRUNC, 4, 1 },
    { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 },
    { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 },
    { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 },
@@ -62,7 +71,7 @@ static const slang_ir_info IrInfo[] = {
    { 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_DDY, "IR_DDY", OPCODE_DDY, 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 },
@@ -71,6 +80,7 @@ static const slang_ir_info IrInfo[] = {
    { IR_NOISE4, "IR_NOISE4", OPCODE_NOISE4, 1, 1 },
 
    /* other */
+   { IR_CMP, "IR_CMP", OPCODE_CMP, 4, 3 },  /* compare/select */
    { IR_SEQ, "IR_SEQ", OPCODE_NOP, 0, 0 },
    { IR_SCOPE, "IR_SCOPE", OPCODE_NOP, 0, 0 },
    { IR_LABEL, "IR_LABEL", OPCODE_NOP, 0, 0 },
@@ -78,18 +88,22 @@ static const slang_ir_info IrInfo[] = {
    { 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_COPY, "IR_COPY", 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_TEX_SH, "IR_TEX_SH", OPCODE_TEX, 4, 1 },
+   { IR_TEXB_SH, "IR_TEXB_SH", OPCODE_TXB, 4, 1 },
+   { IR_TEXP_SH, "IR_TEXP_SH", 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 }
+   { IR_NOP, "IR_NOP", OPCODE_NOP, 0, 0 },
+   { 0, NULL, 0, 0, 0 }
 };
 
 
@@ -106,6 +120,136 @@ _slang_ir_info(slang_ir_opcode opcode)
 }
 
 
+void
+_slang_init_ir_storage(slang_ir_storage *st,
+                       gl_register_file file, GLint index, GLint size,
+                       GLuint swizzle)
+{
+   st->File = file;
+   st->Index = index;
+   st->Size = size;
+   st->Swizzle = swizzle;
+   st->Parent = NULL;
+   st->IsIndirect = GL_FALSE;
+}
+
+
+/**
+ * Return a new slang_ir_storage object.
+ */
+slang_ir_storage *
+_slang_new_ir_storage(gl_register_file file, GLint index, GLint size)
+{
+   slang_ir_storage *st;
+   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+   if (st) {
+      st->File = file;
+      st->Index = index;
+      st->Size = size;
+      st->Swizzle = SWIZZLE_NOOP;
+      st->Parent = NULL;
+      st->IsIndirect = GL_FALSE;
+   }
+   return st;
+}
+
+
+/**
+ * Return a new slang_ir_storage object.
+ */
+slang_ir_storage *
+_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
+                          GLuint swizzle)
+{
+   slang_ir_storage *st;
+   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+   if (st) {
+      st->File = file;
+      st->Index = index;
+      st->Size = size;
+      st->Swizzle = swizzle;
+      st->Parent = NULL;
+      st->IsIndirect = GL_FALSE;
+   }
+   return st;
+}
+
+
+/**
+ * Return a new slang_ir_storage object.
+ */
+slang_ir_storage *
+_slang_new_ir_storage_relative(GLint index, GLint size,
+                               slang_ir_storage *parent)
+{
+   slang_ir_storage *st;
+   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+   if (st) {
+      st->File = PROGRAM_UNDEFINED;
+      st->Index = index;
+      st->Size = size;
+      st->Swizzle = SWIZZLE_NOOP;
+      st->Parent = parent;
+      st->IsIndirect = GL_FALSE;
+   }
+   return st;
+}
+
+
+slang_ir_storage *
+_slang_new_ir_storage_indirect(gl_register_file file,
+                               GLint index,
+                               GLint size,
+                               gl_register_file indirectFile,
+                               GLint indirectIndex,
+                               GLuint indirectSwizzle)
+{
+   slang_ir_storage *st;
+   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+   if (st) {
+      st->File = file;
+      st->Index = index;
+      st->Size = size;
+      st->Swizzle = SWIZZLE_NOOP;
+      st->IsIndirect = GL_TRUE;
+      st->IndirectFile = indirectFile;
+      st->IndirectIndex = indirectIndex;
+      st->IndirectSwizzle = indirectSwizzle;
+   }
+   return st;
+}
+
+
+/**
+ * Allocate IR storage for a texture sampler.
+ * \param sampNum  the sampler number/index
+ * \param texTarget  one of TEXTURE_x_INDEX values
+ * \param size  number of samplers (in case of sampler array)
+ */
+slang_ir_storage *
+_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size)
+{
+   slang_ir_storage *st;
+   assert(texTarget < NUM_TEXTURE_TARGETS);
+   st = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, size);
+   if (st) {
+      st->TexTarget = texTarget;
+   }
+   return st;
+}
+
+
+
+/* XXX temporary function */
+void
+_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src)
+{
+   *dst = *src;
+   dst->Parent = NULL;
+}
+
+
+
 static const char *
 _slang_ir_name(slang_ir_opcode opcode)
 {
@@ -113,6 +257,8 @@ _slang_ir_name(slang_ir_opcode opcode)
 }
 
 
+
+#if 0 /* no longer needed with mempool */
 /**
  * Since many IR nodes might point to the same IR storage info, we need
  * to be careful when deleting things.
@@ -131,6 +277,7 @@ _slang_refcount_storage(slang_ir_node *n)
    for (i = 0; i < 3; i++)
       _slang_refcount_storage(n->Children[i]);
 }
+#endif
 
 
 static void
@@ -140,20 +287,20 @@ _slang_free_ir(slang_ir_node *n)
    if (!n)
       return;
 
+#if 0
    if (n->Store) {
       n->Store->RefCount--;
       if (n->Store->RefCount == 0) {
-#if 0
-         free(n->Store);
-#endif
+         _slang_free(n->Store);
          n->Store = NULL;
       }
    }
+#endif
 
    for (i = 0; i < 3; i++)
       _slang_free_ir(n->Children[i]);
    /* Do not free n->List since it's a child elsewhere */
-   free(n);
+   _slang_free(n);
 }
 
 
@@ -163,41 +310,13 @@ _slang_free_ir(slang_ir_node *n)
 void
 _slang_free_ir_tree(slang_ir_node *n)
 {
+#if 0
    _slang_refcount_storage(n);
+#endif
    _slang_free_ir(n);
 }
 
 
-
-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)
 {
@@ -211,12 +330,14 @@ storage_string(const slang_ir_storage *st)
       "NAMED_PARAM",
       "CONSTANT",
       "UNIFORM",
+      "VARYING",
       "WRITE_ONLY",
       "ADDRESS",
       "SAMPLER",
       "UNDEFINED"
    };
    static char s[100];
+   assert(Elements(files) == PROGRAM_FILE_MAX);
 #if 0
    if (st->Size == 1)
       sprintf(s, "%s[%d]", files[st->File], st->Index);
@@ -268,8 +389,8 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
       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));
+   case IR_COPY:
+      printf("COPY\n");
       _slang_print_ir_tree(n->Children[0], indent+3);
       _slang_print_ir_tree(n->Children[1], indent+3);
       break;
@@ -306,7 +427,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
       printf("RETURN\n");
       break;
    case IR_CALL:
-      printf("CALL\n");
+      printf("CALL %s\n", n->Label->Name);
       break;
 
    case IR_LOOP:
@@ -326,10 +447,6 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
    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);
@@ -342,7 +459,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
    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),
+             _mesa_swizzle_string(n->Store->Swizzle, 0, 0),
              storage_string(n->Store), (void*) n->Store);
       break;
    case IR_VAR_DECL:
@@ -369,7 +486,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
       break;
    case IR_SWIZZLE:
       printf("SWIZZLE %s of  (store %p) \n",
-             swizzle_string(n->Store->Swizzle), (void*) n->Store);
+             _mesa_swizzle_string(n->Store->Swizzle, 0, 0), (void*) n->Store);
       _slang_print_ir_tree(n->Children[0], indent + 3);
       break;
    default: