Store AST function call parameters in expressions
[mesa.git] / ast_to_hir.cpp
index 52e372c7e493eab128922eac12b93b352a1d8e33..357683f0c3de5f84c2860a895ab6b4137c2a01c4 100644 (file)
@@ -1381,7 +1381,7 @@ ast_type_specifier::glsl_type(const char **name,
 {
    const struct glsl_type *type;
 
-   if (this->type_specifier == ast_struct) {
+   if ((this->type_specifier == ast_struct) && (this->type_name == NULL)) {
       /* FINISHME: Handle annonymous structures. */
       type = NULL;
    } else {
@@ -1476,6 +1476,12 @@ ast_declarator_list::hir(exec_list *instructions,
    const struct glsl_type *decl_type;
    const char *type_name = NULL;
    ir_rvalue *result = NULL;
+   YYLTYPE loc = this->get_location();
+
+   /* The type specifier may contain a structure definition.  Process that
+    * before any of the variable declarations.
+    */
+   (void) this->type->specifier->hir(instructions, state);
 
    /* FINISHME: Handle vertex shader "invariant" declarations that do not
     * FINISHME: include a type.  These re-declare built-in variables to be
@@ -1483,12 +1489,27 @@ ast_declarator_list::hir(exec_list *instructions,
     */
 
    decl_type = this->type->specifier->glsl_type(& type_name, state);
+   if (is_empty_list(&this->declarations)) {
+      /* There are only two valid cases where the declaration list can be
+       * empty.
+       *
+       * 1. The declaration is setting the default precision of a built-in
+       *    type (e.g., 'precision highp vec4;').
+       *
+       * 2. Adding 'invariant' to an existing vertex shader output.
+       */
+
+      if (this->type->qualifier.invariant) {
+      } else if (decl_type != NULL) {
+      } else {
+           _mesa_glsl_error(& loc, state, "incomplete declaration");
+      }
+   }
 
    foreach (ptr, &this->declarations) {
       struct ast_declaration *const decl = (struct ast_declaration * )ptr;
       const struct glsl_type *var_type;
       struct ir_variable *var;
-      YYLTYPE loc = this->get_location();
 
       /* FINISHME: Emit a warning if a variable declaration shadows a
        * FINISHME: declaration at a higher scope.
@@ -1973,20 +1994,9 @@ ast_function::hir(exec_list *instructions,
    if (sig == NULL) {
       sig = new ir_function_signature(return_type);
       f->add_signature(sig);
-   } else if (is_definition) {
-      /* Destroy all of the previous parameter information.  The previous
-       * parameter information comes from the function prototype, and it can
-       * either include invalid parameter names or may not have names at all.
-       */
-      foreach_iter(exec_list_iterator, iter, sig->parameters) {
-        assert(((ir_instruction *) iter.get())->as_variable() != NULL);
-
-        iter.remove();
-        delete iter.get();
-      }
    }
 
-   hir_parameters.move_nodes_to(& sig->parameters);
+   sig->replace_parameters(&hir_parameters);
    signature = sig;
 
    /* Function declarations (prototypes) do not have r-values.
@@ -2267,3 +2277,117 @@ ast_iteration_statement::hir(exec_list *instructions,
     */
    return NULL;
 }
+
+
+ir_rvalue *
+ast_type_specifier::hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   if (this->structure != NULL)
+      return this->structure->hir(instructions, state);
+
+   return NULL;
+}
+
+
+ir_rvalue *
+ast_struct_specifier::hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   simple_node *ptr;
+   unsigned decl_count = 0;
+
+   /* Make an initial pass over the list of structure fields to determine how
+    * many there are.  Each element in this list is an ast_declarator_list.
+    * This means that we actually need to count the number of elements in the
+    * 'declarations' list in each of the elements.
+    */
+   foreach (ptr, & this->declarations) {
+      ast_declarator_list *decl_list = (ast_declarator_list *) ptr;
+      simple_node *decl_ptr;
+
+      foreach (decl_ptr, & decl_list->declarations) {
+        decl_count++;
+      }
+   }
+
+
+   /* Allocate storage for the structure fields and process the field
+    * declarations.  As the declarations are processed, try to also convert
+    * the types to HIR.  This ensures that structure definitions embedded in
+    * other structure definitions are processed.
+    */
+   glsl_struct_field *const fields = (glsl_struct_field *)
+      malloc(sizeof(*fields) * decl_count);
+
+   unsigned i = 0;
+   foreach (ptr, & this->declarations) {
+      ast_declarator_list *decl_list = (ast_declarator_list *) ptr;
+      simple_node *decl_ptr;
+      const char *type_name;
+
+      decl_list->type->specifier->hir(instructions, state);
+
+      const glsl_type *decl_type =
+        decl_list->type->specifier->glsl_type(& type_name, state);
+
+      foreach (decl_ptr, & decl_list->declarations) {
+        ast_declaration *const decl = (ast_declaration *) decl_ptr;
+        const struct glsl_type *const field_type =
+           (decl->is_array)
+           ? process_array_type(decl_type, decl->array_size, state)
+           : decl_type;
+
+        fields[i].type = (field_type != NULL)
+           ? field_type : glsl_type::error_type;
+        fields[i].name = decl->identifier;
+        i++;
+      }
+   }
+
+   assert(i == decl_count);
+
+   const char *name;
+   if (this->name == NULL) {
+      static unsigned anon_count = 1;
+      char buf[32];
+
+      snprintf(buf, sizeof(buf), "#anon_struct_%04x", anon_count);
+      anon_count++;
+
+      name = strdup(buf);
+   } else {
+      name = this->name;
+   }
+
+   glsl_type *t = new glsl_type(fields, decl_count, name);
+
+   YYLTYPE loc = this->get_location();
+   if (!state->symbols->add_type(name, t)) {
+      _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
+   } else {
+      /* This logic is a bit tricky.  It is an error to declare a structure at
+       * global scope if there is also a function with the same name.
+       */
+      if ((state->current_function == NULL)
+         && (state->symbols->get_function(name) != NULL)) {
+        _mesa_glsl_error(& loc, state, "name `%s' previously defined", name);
+      } else {
+        t->generate_constructor(state->symbols);
+      }
+
+      const glsl_type **s = (const glsl_type **)
+        realloc(state->user_structures,
+                sizeof(state->user_structures[0]) *
+                (state->num_user_structures + 1));
+      if (s != NULL) {
+        s[state->num_user_structures] = t;
+        state->user_structures = s;
+        state->num_user_structures++;
+      }
+   }
+
+   /* Structure type definitions do not have r-values.
+    */
+   return NULL;
+}