glsl/linker: add check for compute shared memory size
[mesa.git] / src / compiler / glsl / ir.cpp
index 2d0c4c051abb118810d87a8b138b670fa29b323d..18bf1eb6386628e8738cceb8d70e63e39e4ee138 100644 (file)
@@ -203,11 +203,16 @@ ir_expression::ir_expression(int op, const struct glsl_type *type,
    this->operands[1] = op1;
    this->operands[2] = op2;
    this->operands[3] = op3;
+   init_num_operands();
+
 #ifndef NDEBUG
-   int num_operands = get_num_operands(this->operation);
-   for (int i = num_operands; i < 4; i++) {
+   for (unsigned i = num_operands; i < 4; i++) {
       assert(this->operands[i] == NULL);
    }
+
+   for (unsigned i = 0; i < num_operands; i++) {
+      assert(this->operands[i] != NULL);
+   }
 #endif
 }
 
@@ -221,6 +226,9 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
    this->operands[3] = NULL;
 
    assert(op <= ir_last_unop);
+   init_num_operands();
+   assert(num_operands == 1);
+   assert(this->operands[0]);
 
    switch (this->operation) {
    case ir_unop_bit_not:
@@ -425,6 +433,11 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
    this->operands[3] = NULL;
 
    assert(op > ir_last_unop);
+   init_num_operands();
+   assert(num_operands == 2);
+   for (unsigned i = 0; i < num_operands; i++) {
+      assert(this->operands[i] != NULL);
+   }
 
    switch (this->operation) {
    case ir_binop_all_equal:
@@ -519,6 +532,11 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1,
    this->operands[3] = NULL;
 
    assert(op > ir_last_binop && op <= ir_last_triop);
+   init_num_operands();
+   assert(num_operands == 3);
+   for (unsigned i = 0; i < num_operands; i++) {
+      assert(this->operands[i] != NULL);
+   }
 
    switch (this->operation) {
    case ir_triop_fma:
@@ -538,7 +556,11 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1,
    }
 }
 
-unsigned int
+/**
+ * This is only here for ir_reader to used for testing purposes. Please use
+ * the precomputed num_operands field if you need the number of operands.
+ */
+unsigned
 ir_expression::get_num_operands(ir_expression_operation op)
 {
    assert(op <= ir_last_opcode);
@@ -555,8 +577,7 @@ ir_expression::get_num_operands(ir_expression_operation op)
    if (op <= ir_last_quadop)
       return 4;
 
-   assert(false);
-   return 0;
+   unreachable("Could not calculate number of operands");
 }
 
 #include "ir_expression_operation_strings.h"
@@ -606,14 +627,14 @@ ir_expression::variable_referenced() const
 ir_constant::ir_constant()
    : ir_rvalue(ir_type_constant)
 {
-   this->array_elements = NULL;
+   this->const_elements = NULL;
 }
 
 ir_constant::ir_constant(const struct glsl_type *type,
                         const ir_constant_data *data)
    : ir_rvalue(ir_type_constant)
 {
-   this->array_elements = NULL;
+   this->const_elements = NULL;
 
    assert((type->base_type >= GLSL_TYPE_UINT)
          && (type->base_type <= GLSL_TYPE_IMAGE));
@@ -716,7 +737,7 @@ ir_constant::ir_constant(bool b, unsigned vector_elements)
 ir_constant::ir_constant(const ir_constant *c, unsigned i)
    : ir_rvalue(ir_type_constant)
 {
-   this->array_elements = NULL;
+   this->const_elements = NULL;
    this->type = c->type->get_base_type();
 
    switch (this->type->base_type) {
@@ -732,34 +753,25 @@ ir_constant::ir_constant(const ir_constant *c, unsigned i)
 ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
    : ir_rvalue(ir_type_constant)
 {
-   this->array_elements = NULL;
+   this->const_elements = NULL;
    this->type = type;
 
    assert(type->is_scalar() || type->is_vector() || type->is_matrix()
          || type->is_record() || type->is_array());
 
-   if (type->is_array()) {
-      this->array_elements = ralloc_array(this, ir_constant *, type->length);
-      unsigned i = 0;
-      foreach_in_list(ir_constant, value, value_list) {
-        assert(value->as_constant() != NULL);
-
-        this->array_elements[i++] = value;
-      }
-      return;
-   }
-
    /* If the constant is a record, the types of each of the entries in
     * value_list must be a 1-for-1 match with the structure components.  Each
     * entry must also be a constant.  Just move the nodes from the value_list
     * to the list in the ir_constant.
     */
-   /* FINISHME: Should there be some type checking and / or assertions here? */
-   /* FINISHME: Should the new constant take ownership of the nodes from
-    * FINISHME: value_list, or should it make copies?
-    */
-   if (type->is_record()) {
-      value_list->move_nodes_to(& this->components);
+   if (type->is_array() || type->is_record()) {
+      this->const_elements = ralloc_array(this, ir_constant *, type->length);
+      unsigned i = 0;
+      foreach_in_list(ir_constant, value, value_list) {
+        assert(value->as_constant() != NULL);
+
+        this->const_elements[i++] = value;
+      }
       return;
    }
 
@@ -903,16 +915,18 @@ ir_constant::zero(void *mem_ctx, const glsl_type *type)
    memset(&c->value, 0, sizeof(c->value));
 
    if (type->is_array()) {
-      c->array_elements = ralloc_array(c, ir_constant *, type->length);
+      c->const_elements = ralloc_array(c, ir_constant *, type->length);
 
       for (unsigned i = 0; i < type->length; i++)
-        c->array_elements[i] = ir_constant::zero(c, type->fields.array);
+        c->const_elements[i] = ir_constant::zero(c, type->fields.array);
    }
 
    if (type->is_record()) {
+      c->const_elements = ralloc_array(c, ir_constant *, type->length);
+
       for (unsigned i = 0; i < type->length; i++) {
-        ir_constant *comp = ir_constant::zero(mem_ctx, type->fields.structure[i].type);
-        c->components.push_tail(comp);
+         c->const_elements[i] =
+            ir_constant::zero(mem_ctx, type->fields.structure[i].type);
       }
    }
 
@@ -1079,32 +1093,16 @@ ir_constant::get_array_element(unsigned i) const
    else if (i >= this->type->length)
       i = this->type->length - 1;
 
-   return array_elements[i];
+   return const_elements[i];
 }
 
 ir_constant *
-ir_constant::get_record_field(const char *name)
+ir_constant::get_record_field(int idx)
 {
-   int idx = this->type->field_index(name);
+   assert(this->type->is_record());
+   assert(idx >= 0 && (unsigned) idx < this->type->length);
 
-   if (idx < 0)
-      return NULL;
-
-   if (this->components.is_empty())
-      return NULL;
-
-   exec_node *node = this->components.get_head_raw();
-   for (int i = 0; i < idx; i++) {
-      node = node->next;
-
-      /* If the end of the list is encountered before the element matching the
-       * requested field is found, return NULL.
-       */
-      if (node->is_tail_sentinel())
-        return NULL;
-   }
-
-   return (ir_constant *) node;
+   return const_elements[idx];
 }
 
 void
@@ -1150,19 +1148,11 @@ ir_constant::copy_offset(ir_constant *src, int offset)
       break;
    }
 
-   case GLSL_TYPE_STRUCT: {
-      assert (src->type == this->type);
-      this->components.make_empty();
-      foreach_in_list(ir_constant, orig, &src->components) {
-        this->components.push_tail(orig->clone(this, NULL));
-      }
-      break;
-   }
-
+   case GLSL_TYPE_STRUCT:
    case GLSL_TYPE_ARRAY: {
       assert (src->type == this->type);
       for (unsigned i = 0; i < this->type->length; i++) {
-        this->array_elements[i] = src->array_elements[i]->clone(this, NULL);
+        this->const_elements[i] = src->const_elements[i]->clone(this, NULL);
       }
       break;
    }
@@ -1222,34 +1212,14 @@ ir_constant::has_value(const ir_constant *c) const
    if (this->type != c->type)
       return false;
 
-   if (this->type->is_array()) {
+   if (this->type->is_array() || this->type->is_record()) {
       for (unsigned i = 0; i < this->type->length; i++) {
-        if (!this->array_elements[i]->has_value(c->array_elements[i]))
+        if (!this->const_elements[i]->has_value(c->const_elements[i]))
            return false;
       }
       return true;
    }
 
-   if (this->type->is_record()) {
-      const exec_node *a_node = this->components.get_head_raw();
-      const exec_node *b_node = c->components.get_head_raw();
-
-      while (!a_node->is_tail_sentinel()) {
-        assert(!b_node->is_tail_sentinel());
-
-        const ir_constant *const a_field = (ir_constant *) a_node;
-        const ir_constant *const b_field = (ir_constant *) b_node;
-
-        if (!a_field->has_value(b_field))
-           return false;
-
-        a_node = a_node->next;
-        b_node = b_node->next;
-      }
-
-      return true;
-   }
-
    for (unsigned i = 0; i < this->type->components(); i++) {
       switch (this->type->base_type) {
       case GLSL_TYPE_UINT:
@@ -1431,8 +1401,8 @@ ir_dereference_record::ir_dereference_record(ir_rvalue *value,
    assert(value != NULL);
 
    this->record = value;
-   this->field = ralloc_strdup(this, field);
    this->type = this->record->type->field_type(field);
+   this->field_idx = this->record->type->field_index(field);
 }
 
 
@@ -1443,8 +1413,8 @@ ir_dereference_record::ir_dereference_record(ir_variable *var,
    void *ctx = ralloc_parent(var);
 
    this->record = new(ctx) ir_dereference_variable(var);
-   this->field = ralloc_strdup(this, field);
    this->type = this->record->type->field_type(field);
+   this->field_idx = this->record->type->field_index(field);
 }
 
 bool
@@ -1590,7 +1560,7 @@ ir_swizzle::ir_swizzle(ir_rvalue *val, const unsigned *comp,
 }
 
 ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask)
-   : ir_rvalue(ir_type_swizzle), mask(mask), val(val)
+   : ir_rvalue(ir_type_swizzle), val(val), mask(mask)
 {
    this->type = glsl_type::get_instance(val->type->base_type,
                                        mask.num_components, 1);
@@ -1950,15 +1920,10 @@ steal_memory(ir_instruction *ir, void *new_ctx)
    /* The components of aggregate constants are not visited by the normal
     * visitor, so steal their values by hand.
     */
-   if (constant != NULL) {
-      if (constant->type->is_record()) {
-        foreach_in_list(ir_constant, field, &constant->components) {
-           steal_memory(field, ir);
-        }
-      } else if (constant->type->is_array()) {
-        for (unsigned int i = 0; i < constant->type->length; i++) {
-           steal_memory(constant->array_elements[i], ir);
-        }
+   if (constant != NULL &&
+       (constant->type->is_array() || constant->type->is_record())) {
+      for (unsigned int i = 0; i < constant->type->length; i++) {
+         steal_memory(constant->const_elements[i], ir);
       }
    }