linker: Limit attribute allocation to MAX_VERTEX_ATTRIBS
[mesa.git] / glsl_types.cpp
index b7abdaef2ce0f8053ae31e5d45640e99d4a3f681..2b7c5bce30ff6de9b05ecaacf81cec8d7116a815 100644 (file)
@@ -90,6 +90,15 @@ generate_ARB_texture_rectangle_types(glsl_symbol_table *symtab, bool warn)
 }
 
 
+static void
+generate_EXT_texture_array_types(glsl_symbol_table *symtab, bool warn)
+{
+   add_types_to_symbol_table(symtab, builtin_EXT_texture_array_types,
+                            Elements(builtin_EXT_texture_array_types),
+                            warn);
+}
+
+
 void
 _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
 {
@@ -112,6 +121,12 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
       generate_ARB_texture_rectangle_types(state->symbols,
                                           state->ARB_texture_rectangle_warn);
    }
+
+   if (state->EXT_texture_array_enable && state->language_version < 130) {
+      // These are already included in 130; don't create twice.
+      generate_EXT_texture_array_types(state->symbols,
+                                      state->EXT_texture_array_warn);
+   }
 }
 
 
@@ -133,11 +148,8 @@ const glsl_type *glsl_type::get_base_type() const
 
 
 ir_function *
-glsl_type::generate_constructor_prototype(glsl_symbol_table *symtab) const
+glsl_type::generate_constructor(glsl_symbol_table *symtab) const
 {
-   /* FINISHME: Add support for non-array types. */
-   assert(base_type == GLSL_TYPE_ARRAY);
-
    /* Generate the function name and add it to the symbol table.
     */
    ir_function *const f = new ir_function(name);
@@ -148,17 +160,47 @@ glsl_type::generate_constructor_prototype(glsl_symbol_table *symtab) const
    ir_function_signature *const sig = new ir_function_signature(this);
    f->add_signature(sig);
 
+   ir_variable **declarations =
+      (ir_variable **) malloc(sizeof(ir_variable *) * this->length);
    for (unsigned i = 0; i < length; i++) {
       char *const param_name = (char *) malloc(10);
 
       snprintf(param_name, 10, "p%08X", i);
 
-      ir_variable *var = new ir_variable(fields.array, param_name);
+      ir_variable *var = (this->base_type == GLSL_TYPE_ARRAY)
+        ? new ir_variable(fields.array, param_name)
+        : new ir_variable(fields.structure[i].type, param_name);
 
       var->mode = ir_var_in;
+      declarations[i] = var;
       sig->parameters.push_tail(var);
    }
 
+   /* Generate the body of the constructor.  The body assigns each of the
+    * parameters to a portion of a local variable called __retval that has
+    * the same type as the constructor.  After initializing __retval,
+    * __retval is returned.
+    */
+   ir_variable *retval = new ir_variable(this, "__retval");
+   sig->body.push_tail(retval);
+
+   for (unsigned i = 0; i < length; i++) {
+      ir_dereference *const lhs = (this->base_type == GLSL_TYPE_ARRAY)
+        ? (ir_dereference *) new ir_dereference_array(retval, new ir_constant(i))
+        : (ir_dereference *) new ir_dereference_record(retval, fields.structure[i].name);
+
+      ir_dereference *const rhs = new ir_dereference_variable(declarations[i]);
+      ir_instruction *const assign = new ir_assignment(lhs, rhs, NULL);
+
+      sig->body.push_tail(assign);
+   }
+
+   free(declarations);
+
+   ir_dereference *const retref = new ir_dereference_variable(retval);
+   ir_instruction *const inst = new ir_return(retref);
+   sig->body.push_tail(inst);
+
    return f;
 }
 
@@ -173,15 +215,12 @@ glsl_type::generate_constructor_prototype(glsl_symbol_table *symtab) const
  *                     scalar parameters.
  * \param parameters   Storage for the list of parameters.  These are
  *                     typically stored in an \c ir_function_signature.
- * \param instructions Storage for the preamble and body of the function.
  * \param declarations Pointers to the variable declarations for the function
  *                     parameters.  These are used later to avoid having to use
  *                     the symbol table.
  */
-static ir_label *
+static ir_function_signature *
 generate_constructor_intro(const glsl_type *type, unsigned parameter_count,
-                          ir_function_signature *const signature,
-                          exec_list *instructions,
                           ir_variable **declarations)
 {
    /* Names of parameters used in vector and matrix constructors
@@ -195,8 +234,7 @@ generate_constructor_intro(const glsl_type *type, unsigned parameter_count,
 
    const glsl_type *const parameter_type = type->get_base_type();
 
-   ir_label *const label = new ir_label(type->name, signature);
-   instructions->push_tail(label);
+   ir_function_signature *const signature = new ir_function_signature(type);
 
    for (unsigned i = 0; i < parameter_count; i++) {
       ir_variable *var = new ir_variable(parameter_type, names[i]);
@@ -204,11 +242,6 @@ generate_constructor_intro(const glsl_type *type, unsigned parameter_count,
       var->mode = ir_var_in;
       signature->parameters.push_tail(var);
 
-      var = new ir_variable(parameter_type, names[i]);
-
-      var->mode = ir_var_in;
-      signature->body.push_tail(var);
-
       declarations[i] = var;
    }
 
@@ -216,7 +249,7 @@ generate_constructor_intro(const glsl_type *type, unsigned parameter_count,
    signature->body.push_tail(retval);
 
    declarations[16] = retval;
-   return label;
+   return signature;
 }
 
 
@@ -232,15 +265,16 @@ generate_vec_body_from_scalar(exec_list *instructions,
    /* Generate a single assignment of the parameter to __retval.x and return
     * __retval.xxxx for however many vector components there are.
     */
-   ir_dereference *const lhs_ref = new ir_dereference(declarations[16]);
-   ir_dereference *const rhs = new ir_dereference(declarations[0]);
+   ir_dereference *const lhs_ref =
+      new ir_dereference_variable(declarations[16]);
+   ir_dereference *const rhs = new ir_dereference_variable(declarations[0]);
 
    ir_swizzle *lhs = new ir_swizzle(lhs_ref, 0, 0, 0, 0, 1);
 
    inst = new ir_assignment(lhs, rhs, NULL);
    instructions->push_tail(inst);
 
-   ir_dereference *const retref = new ir_dereference(declarations[16]);
+   ir_dereference *const retref = new ir_dereference_variable(declarations[16]);
 
    ir_swizzle *retval = new ir_swizzle(retref, 0, 0, 0, 0,
                                        declarations[16]->type->vector_elements);
@@ -265,16 +299,17 @@ generate_vec_body_from_N_scalars(exec_list *instructions,
     * __retval.x and return __retval.
     */
    for (unsigned i = 0; i < vec_type->vector_elements; i++) {
-      ir_dereference *const lhs_ref = new ir_dereference(declarations[16]);
-      ir_dereference *const rhs = new ir_dereference(declarations[i]);
+      ir_dereference *const lhs_ref =
+        new ir_dereference_variable(declarations[16]);
+      ir_dereference *const rhs = new ir_dereference_variable(declarations[i]);
 
-      ir_swizzle *lhs = new ir_swizzle(lhs_ref, 1, 0, 0, 0, 1);
+      ir_swizzle *lhs = new ir_swizzle(lhs_ref, i, 0, 0, 0, 1);
 
       inst = new ir_assignment(lhs, rhs, NULL);
       instructions->push_tail(inst);
    }
 
-   ir_dereference *retval = new ir_dereference(declarations[16]);
+   ir_dereference *retval = new ir_dereference_variable(declarations[16]);
 
    inst = new ir_return(retval);
    instructions->push_tail(inst);
@@ -316,19 +351,18 @@ generate_mat_body_from_scalar(exec_list *instructions,
 
    instructions->push_tail(column);
 
-   ir_dereference *const lhs_ref = new ir_dereference(column);
-   ir_dereference *const rhs = new ir_dereference(declarations[0]);
+   ir_dereference *const lhs_ref = new ir_dereference_variable(column);
+   ir_dereference *const rhs = new ir_dereference_variable(declarations[0]);
 
    ir_swizzle *lhs = new ir_swizzle(lhs_ref, 0, 0, 0, 0, 1);
 
    inst = new ir_assignment(lhs, rhs, NULL);
    instructions->push_tail(inst);
 
-   const float z = 0.0f;
-   ir_constant *const zero = new ir_constant(glsl_type::float_type, &z);
+   ir_constant *const zero = new ir_constant(0.0f);
 
    for (unsigned i = 1; i < column_type->vector_elements; i++) {
-      ir_dereference *const lhs_ref = new ir_dereference(column);
+      ir_dereference *const lhs_ref = new ir_dereference_variable(column);
 
       ir_swizzle *lhs = new ir_swizzle(lhs_ref, i, 0, 0, 0, 1);
 
@@ -339,7 +373,7 @@ generate_mat_body_from_scalar(exec_list *instructions,
 
    for (unsigned i = 0; i < row_type->vector_elements; i++) {
       static const unsigned swiz[] = { 1, 1, 1, 0, 1, 1, 1 };
-      ir_dereference *const rhs_ref = new ir_dereference(column);
+      ir_dereference *const rhs_ref = new ir_dereference_variable(column);
 
       /* This will be .xyyy when i=0, .yxyy when i=1, etc.
        */
@@ -347,14 +381,15 @@ generate_mat_body_from_scalar(exec_list *instructions,
                                        swiz[5 - i], swiz[6 - i],
                                       column_type->vector_elements);
 
-      ir_constant *const idx = new ir_constant(glsl_type::int_type, &i);
-      ir_dereference *const lhs = new ir_dereference(declarations[16], idx);
+      ir_constant *const idx = new ir_constant(int(i));
+      ir_dereference *const lhs =
+        new ir_dereference_array(declarations[16], idx);
 
       inst = new ir_assignment(lhs, rhs, NULL);
       instructions->push_tail(inst);
    }
 
-   ir_dereference *const retval = new ir_dereference(declarations[16]);
+   ir_dereference *const retval = new ir_dereference_variable(declarations[16]);
    inst = new ir_return(retval);
    instructions->push_tail(inst);
 }
@@ -377,25 +412,23 @@ generate_mat_body_from_N_scalars(exec_list *instructions,
     */
    for (unsigned i = 0; i < column_type->vector_elements; i++) {
       for (unsigned j = 0; j < row_type->vector_elements; j++) {
-        ir_constant *row_index = new ir_constant(glsl_type::int_type, &i);
+        ir_constant *row_index = new ir_constant(int(i));
         ir_dereference *const row_access =
-           new ir_dereference(declarations[16], row_index);
+           new ir_dereference_array(declarations[16], row_index);
 
-        ir_dereference *const component_access_ref =
-           new ir_dereference(row_access);
-
-        ir_swizzle *component_access = new ir_swizzle(component_access_ref,
+        ir_swizzle *component_access = new ir_swizzle(row_access,
                                                       j, 0, 0, 0, 1);
 
         const unsigned param = (i * row_type->vector_elements) + j;
-        ir_dereference *const rhs = new ir_dereference(declarations[param]);
+        ir_dereference *const rhs =
+           new ir_dereference_variable(declarations[param]);
 
         inst = new ir_assignment(component_access, rhs, NULL);
         instructions->push_tail(inst);
       }
    }
 
-   ir_dereference *retval = new ir_dereference(declarations[16]);
+   ir_dereference *retval = new ir_dereference_variable(declarations[16]);
 
    inst = new ir_return(retval);
    instructions->push_tail(inst);
@@ -425,13 +458,14 @@ generate_constructor(glsl_symbol_table *symtab, const struct glsl_type *types,
       if (types[i].is_scalar())
         continue;
 
-      /* Generate the function name and add it to the symbol table.
+      /* Generate the function block, add it to the symbol table, and emit it.
        */
       ir_function *const f = new ir_function(types[i].name);
 
       bool added = symtab->add_function(types[i].name, f);
       assert(added);
 
+      instructions->push_tail(f);
 
       /* Each type has several basic constructors.  The total number of forms
        * depends on the derived type.
@@ -450,41 +484,32 @@ generate_constructor(glsl_symbol_table *symtab, const struct glsl_type *types,
        * expectation is that the IR generator will generate a call to the
        * appropriate from-scalars constructor.
        */
-      ir_function_signature *const sig = new ir_function_signature(& types[i]);
+      ir_function_signature *const sig =
+         generate_constructor_intro(&types[i], 1, declarations);
       f->add_signature(sig);
 
-      sig->definition =
-        generate_constructor_intro(& types[i], 1, sig,
-                                   instructions, declarations);
-
       if (types[i].is_vector()) {
         generate_vec_body_from_scalar(&sig->body, declarations);
 
         ir_function_signature *const vec_sig =
-           new ir_function_signature(& types[i]);
+           generate_constructor_intro(&types[i], types[i].vector_elements,
+                                      declarations);
         f->add_signature(vec_sig);
 
-        vec_sig->definition =
-           generate_constructor_intro(& types[i], types[i].vector_elements,
-                                      vec_sig, instructions,
-                                      declarations);
-        generate_vec_body_from_N_scalars(&sig->body, declarations);
+        generate_vec_body_from_N_scalars(&vec_sig->body, declarations);
       } else {
         assert(types[i].is_matrix());
 
         generate_mat_body_from_scalar(&sig->body, declarations);
 
         ir_function_signature *const mat_sig =
-           new ir_function_signature(& types[i]);
-        f->add_signature(mat_sig);
-
-        mat_sig->definition =
-           generate_constructor_intro(& types[i],
+           generate_constructor_intro(&types[i],
                                       (types[i].vector_elements
                                        * types[i].matrix_columns),
-                                      mat_sig, instructions,
                                       declarations);
-        generate_mat_body_from_N_scalars(instructions, declarations);
+        f->add_signature(mat_sig);
+
+        generate_mat_body_from_N_scalars(&mat_sig->body, declarations);
       }
    }
 }
@@ -677,3 +702,61 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
 
    return t;
 }
+
+
+const glsl_type *
+glsl_type::field_type(const char *name) const
+{
+   if (this->base_type != GLSL_TYPE_STRUCT)
+      return error_type;
+
+   for (unsigned i = 0; i < this->length; i++) {
+      if (strcmp(name, this->fields.structure[i].name) == 0)
+        return this->fields.structure[i].type;
+   }
+
+   return error_type;
+}
+
+
+int
+glsl_type::field_index(const char *name) const
+{
+   if (this->base_type != GLSL_TYPE_STRUCT)
+      return -1;
+
+   for (unsigned i = 0; i < this->length; i++) {
+      if (strcmp(name, this->fields.structure[i].name) == 0)
+        return i;
+   }
+
+   return -1;
+}
+
+
+unsigned
+glsl_type::component_slots() const
+{
+   switch (this->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_BOOL:
+      return this->components();
+
+   case GLSL_TYPE_STRUCT: {
+      unsigned size = 0;
+
+      for (unsigned i = 0; i < this->length; i++)
+        size += this->fields.structure[i].type->component_slots();
+
+      return size;
+   }
+
+   case GLSL_TYPE_ARRAY:
+      return this->length * this->fields.array->component_slots();
+
+   default:
+      return 0;
+   }
+}