r300: move some more function to generic
[mesa.git] / src / mesa / shader / slang / slang_compile_operation.c
index aa66be889581da3f5e695a0d54d28d168da746ba..53cf6faff9796a7b009bfe5591a2cd1913024f2d 100644 (file)
@@ -28,8 +28,9 @@
  * \author Michal Krol
  */
 
-#include "imports.h"
+#include "main/imports.h"
 #include "slang_compile.h"
+#include "slang_mem.h"
 
 
 /**
@@ -42,6 +43,7 @@ slang_operation_construct(slang_operation * oper)
    oper->children = NULL;
    oper->num_children = 0;
    oper->literal[0] = 0.0;
+   oper->literal_size = 1;
    oper->a_id = SLANG_ATOM_NULL;
    oper->locals = _slang_variable_scope_new(NULL);
    if (oper->locals == NULL)
@@ -59,16 +61,52 @@ slang_operation_destruct(slang_operation * oper)
 
    for (i = 0; i < oper->num_children; i++)
       slang_operation_destruct(oper->children + i);
-   slang_alloc_free(oper->children);
+   _slang_free(oper->children);
    slang_variable_scope_destruct(oper->locals);
-   slang_alloc_free(oper->locals);
+   _slang_free(oper->locals);
    oper->children = NULL;
    oper->num_children = 0;
    oper->locals = NULL;
 }
 
+
+/**
+ * Recursively traverse 'oper', replacing occurances of 'oldScope' with
+ * 'newScope' in the oper->locals->outer_scope field.
+ */
+void
+slang_replace_scope(slang_operation *oper,
+                    slang_variable_scope *oldScope,
+                    slang_variable_scope *newScope)
+{
+   GLuint i;
+
+   if (oper->locals != newScope &&
+       oper->locals->outer_scope == oldScope) {
+      /* found.  replace old w/ new */
+      oper->locals->outer_scope = newScope;
+   }
+
+   if (oper->type == SLANG_OPER_VARIABLE_DECL) {
+      /* search/replace in the initializer */
+      slang_variable *var;
+      var = _slang_locate_variable(oper->locals, oper->a_id, GL_TRUE);
+      if (var && var->initializer) {
+         slang_replace_scope(var->initializer, oldScope, newScope);
+      }
+   }
+
+   /* search/replace in children */
+   for (i = 0; i < oper->num_children; i++) {
+      slang_replace_scope(&oper->children[i], oldScope, newScope);
+   }
+}
+
+
 /**
  * Recursively copy a slang_operation node.
+ * \param x  copy target
+ * \param y  copy source
  * \return GL_TRUE for success, GL_FALSE if failure
  */
 GLboolean
@@ -81,7 +119,7 @@ slang_operation_copy(slang_operation * x, const slang_operation * y)
       return GL_FALSE;
    z.type = y->type;
    z.children = (slang_operation *)
-      slang_alloc_malloc(y->num_children * sizeof(slang_operation));
+      _slang_alloc(y->num_children * sizeof(slang_operation));
    if (z.children == NULL) {
       slang_operation_destruct(&z);
       return GL_FALSE;
@@ -104,6 +142,8 @@ slang_operation_copy(slang_operation * x, const slang_operation * y)
    z.literal[2] = y->literal[2];
    z.literal[3] = y->literal[3];
    z.literal_size = y->literal_size;
+   assert(y->literal_size >= 1);
+   assert(y->literal_size <= 4);
    z.a_id = y->a_id;
    if (y->locals) {
       if (!slang_variable_scope_copy(z.locals, y->locals)) {
@@ -117,6 +157,16 @@ slang_operation_copy(slang_operation * x, const slang_operation * y)
 #endif
    slang_operation_destruct(x);
    *x = z;
+
+   /* If this operation declares a new scope, we need to make sure
+    * all children point to it, not the original operation's scope!
+    */
+   if (x->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+       x->type == SLANG_OPER_WHILE ||
+       x->type == SLANG_OPER_FOR) {
+      slang_replace_scope(x, y->locals, x->locals);
+   }
+
    return GL_TRUE;
 }
 
@@ -125,7 +175,7 @@ slang_operation *
 slang_operation_new(GLuint count)
 {
    slang_operation *ops
-       = (slang_operation *) _mesa_malloc(count * sizeof(slang_operation));
+       = (slang_operation *) _slang_alloc(count * sizeof(slang_operation));
    assert(count > 0);
    if (ops) {
       GLuint i;
@@ -143,7 +193,7 @@ void
 slang_operation_delete(slang_operation *oper)
 {
    slang_operation_destruct(oper);
-   _mesa_free(oper);
+   _slang_free(oper);
 }
 
 
@@ -153,13 +203,13 @@ slang_operation_grow(GLuint *numChildren, slang_operation **children)
    slang_operation *ops;
 
    ops = (slang_operation *)
-      slang_alloc_realloc(*children,
-                          *numChildren * sizeof(slang_operation),
-                          (*numChildren + 1) * sizeof(slang_operation));
+      _slang_realloc(*children,
+                     *numChildren * sizeof(slang_operation),
+                     (*numChildren + 1) * sizeof(slang_operation));
    if (ops) {
       slang_operation *newOp = ops + *numChildren;
       if (!slang_operation_construct(newOp)) {
-         _mesa_free(ops);
+         _slang_free(ops);
          *children = NULL;
          return NULL;
       }
@@ -172,40 +222,52 @@ slang_operation_grow(GLuint *numChildren, slang_operation **children)
 
 /**
  * Insert a new slang_operation into an array.
- * \param numChildren  pointer to current number of children (in/out)
- * \param children  address of array (in/out)
- * \param pos  position to insert
- * \return  pointer to the new operation
+ * \param numElements  pointer to current array size (in/out)
+ * \param array  address of the array (in/out)
+ * \param pos  position to insert new element
+ * \return  pointer to the new operation/element
  */
 slang_operation *
-slang_operation_insert(GLuint *numChildren, slang_operation **children,
+slang_operation_insert(GLuint *numElements, slang_operation **array,
                        GLuint pos)
 {
    slang_operation *ops;
 
-   assert(pos <= *numChildren);
+   assert(pos <= *numElements);
 
    ops = (slang_operation *)
-      _mesa_malloc((*numChildren + 1) * sizeof(slang_operation));
+      _slang_alloc((*numElements + 1) * sizeof(slang_operation));
    if (ops) {
       slang_operation *newOp;
       newOp = ops + pos;
       if (pos > 0)
-         _mesa_memcpy(ops, *children, pos * sizeof(slang_operation));
-      if (pos < *numChildren)
-         _mesa_memcpy(newOp + 1, (*children) + pos,
-                      (*numChildren - pos) * sizeof(slang_operation));
+         _mesa_memcpy(ops, *array, pos * sizeof(slang_operation));
+      if (pos < *numElements)
+         _mesa_memcpy(newOp + 1, (*array) + pos,
+                      (*numElements - pos) * sizeof(slang_operation));
 
       if (!slang_operation_construct(newOp)) {
-         _mesa_free(ops);
-         *numChildren = 0;
-         *children = NULL;
+         _slang_free(ops);
+         *numElements = 0;
+         *array = NULL;
          return NULL;
       }
-      *children = ops;
-      (*numChildren)++;
+      if (*array)
+         _slang_free(*array);
+      *array = ops;
+      (*numElements)++;
       return newOp;
    }
    return NULL;
 }
 
+
+void
+_slang_operation_swap(slang_operation *oper0, slang_operation *oper1)
+{
+   slang_operation tmp = *oper0;
+   *oper0 = *oper1;
+   *oper1 = tmp;
+}
+
+