Replace builtin_types.h generation with the generated output.
[mesa.git] / ast_to_hir.cpp
index 4e1c81917719d5d1f5dfe9969143b2150e2b04db..7b4a855f57674d20852f0dc3e530322e0cd8e72d 100644 (file)
@@ -761,11 +761,8 @@ ast_expression::hir(exec_list *instructions,
       error_emitted = true;
       break;
 
-   case ast_logic_and:
-   case ast_logic_xor:
-   case ast_logic_or:
+   case ast_logic_and: {
       op[0] = this->subexpressions[0]->hir(instructions, state);
-      op[1] = this->subexpressions[1]->hir(instructions, state);
 
       if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
         YYLTYPE loc = this->subexpressions[0]->get_location();
@@ -775,14 +772,125 @@ ast_expression::hir(exec_list *instructions,
         error_emitted = true;
       }
 
-      if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
-        YYLTYPE loc = this->subexpressions[1]->get_location();
+      ir_constant *op0_const = op[0]->constant_expression_value();
+      if (op0_const) {
+        if (op0_const->value.b[0]) {
+           op[1] = this->subexpressions[1]->hir(instructions, state);
+
+           if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+              YYLTYPE loc = this->subexpressions[1]->get_location();
+
+              _mesa_glsl_error(& loc, state,
+                               "RHS of `%s' must be scalar boolean",
+                               operator_string(this->oper));
+              error_emitted = true;
+           }
+           result = op[1];
+        } else {
+           result = op0_const;
+        }
+        type = glsl_type::bool_type;
+      } else {
+        ir_if *const stmt = new ir_if(op[0]);
+        instructions->push_tail(stmt);
+
+        op[1] = this->subexpressions[1]->hir(&stmt->then_instructions, state);
+
+        if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+           YYLTYPE loc = this->subexpressions[1]->get_location();
+
+           _mesa_glsl_error(& loc, state,
+                            "RHS of `%s' must be scalar boolean",
+                            operator_string(this->oper));
+           error_emitted = true;
+        }
+
+        ir_variable *const tmp = generate_temporary(glsl_type::bool_type,
+                                                    instructions, state);
+
+        ir_dereference *const then_deref = new ir_dereference(tmp);
+        ir_assignment *const then_assign =
+           new ir_assignment(then_deref, op[1], NULL);
+        stmt->then_instructions.push_tail(then_assign);
+
+        ir_dereference *const else_deref = new ir_dereference(tmp);
+        ir_assignment *const else_assign =
+           new ir_assignment(else_deref, new ir_constant(false), NULL);
+        stmt->else_instructions.push_tail(else_assign);
 
-        _mesa_glsl_error(& loc, state, "RHS of `%s' must be scalar boolean",
+        result = new ir_dereference(tmp);
+        type = tmp->type;
+      }
+      break;
+   }
+
+   case ast_logic_or: {
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+
+      if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+        YYLTYPE loc = this->subexpressions[0]->get_location();
+
+        _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean",
                          operator_string(this->oper));
         error_emitted = true;
       }
 
+      ir_constant *op0_const = op[0]->constant_expression_value();
+      if (op0_const) {
+        if (op0_const->value.b[0]) {
+           result = op0_const;
+        } else {
+           op[1] = this->subexpressions[1]->hir(instructions, state);
+
+           if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+              YYLTYPE loc = this->subexpressions[1]->get_location();
+
+              _mesa_glsl_error(& loc, state,
+                               "RHS of `%s' must be scalar boolean",
+                               operator_string(this->oper));
+              error_emitted = true;
+           }
+           result = op[1];
+        }
+        type = glsl_type::bool_type;
+      } else {
+        ir_if *const stmt = new ir_if(op[0]);
+        instructions->push_tail(stmt);
+
+        ir_variable *const tmp = generate_temporary(glsl_type::bool_type,
+                                                    instructions, state);
+
+        op[1] = this->subexpressions[1]->hir(&stmt->then_instructions, state);
+
+        if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+           YYLTYPE loc = this->subexpressions[1]->get_location();
+
+           _mesa_glsl_error(& loc, state, "RHS of `%s' must be scalar boolean",
+                            operator_string(this->oper));
+           error_emitted = true;
+        }
+
+        ir_dereference *const then_deref = new ir_dereference(tmp);
+        ir_assignment *const then_assign =
+           new ir_assignment(then_deref, new ir_constant(true), NULL);
+        stmt->then_instructions.push_tail(then_assign);
+
+        ir_dereference *const else_deref = new ir_dereference(tmp);
+        ir_assignment *const else_assign =
+           new ir_assignment(else_deref, op[1], NULL);
+        stmt->else_instructions.push_tail(else_assign);
+
+        result = new ir_dereference(tmp);
+        type = tmp->type;
+      }
+      break;
+   }
+
+   case ast_logic_xor:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      op[1] = this->subexpressions[1]->hir(instructions, state);
+
+
       result = new ir_expression(operations[this->oper], glsl_type::bool_type,
                                 op[0], op[1]);
       type = glsl_type::bool_type;
@@ -1338,6 +1446,15 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
    else
       var->mode = ir_var_auto;
 
+   if (qual->uniform)
+      var->shader_in = true;
+   if (qual->varying) {
+      if (qual->in)
+        var->shader_in = true;
+      if (qual->out)
+        var->shader_out = true;
+   }
+
    if (qual->flat)
       var->interpolation = ir_var_flat;
    else if (qual->noperspective)
@@ -1772,17 +1889,10 @@ parameter_lists_match(exec_list *list_a, exec_list *list_b)
    exec_list_iterator iter_a = list_a->iterator();
    exec_list_iterator iter_b = list_b->iterator();
 
-   while (iter_a.has_next()) {
+   while (iter_a.has_next() && iter_b.has_next()) {
       ir_variable *a = (ir_variable *)iter_a.get();
       ir_variable *b = (ir_variable *)iter_b.get();
 
-      /* If all of the parameters from the other parameter list have been
-       * exhausted, the lists have different length and, by definition,
-       * do not match.
-       */
-      if (!iter_b.has_next())
-        return false;
-
       /* If the types of the parameters do not match, the parameters lists
        * are different.
        */
@@ -1793,6 +1903,12 @@ parameter_lists_match(exec_list *list_a, exec_list *list_b)
       iter_b.next();
    }
 
+   /* Unless both lists are exhausted, they differ in length and, by
+    * definition, do not match.
+    */
+   if (iter_a.has_next() != iter_b.has_next())
+      return false;
+
    return true;
 }
 
@@ -1806,11 +1922,6 @@ ast_function::hir(exec_list *instructions,
    exec_list hir_parameters;
 
 
-   /* The prototype part of a function does not generate anything in the IR
-    * instruction stream.
-    */
-   (void) instructions;
-
    /* Convert the list of function parameters to HIR now so that they can be
     * used below to compare this function's signature with previously seen
     * signatures for functions with the same name.
@@ -1841,9 +1952,39 @@ ast_function::hir(exec_list *instructions,
          * definition.
          */
         if (parameter_lists_match(& hir_parameters, & sig->parameters)) {
-           /* FINISHME: Compare return types. */
+           exec_list_iterator iter_a = hir_parameters.iterator();
+           exec_list_iterator iter_b = sig->parameters.iterator();
+
+           /* check that the qualifiers match. */
+           while (iter_a.has_next()) {
+              ir_variable *a = (ir_variable *)iter_a.get();
+              ir_variable *b = (ir_variable *)iter_b.get();
+
+              if (a->read_only != b->read_only ||
+                  a->interpolation != b->interpolation ||
+                  a->centroid != b->centroid) {
+                 YYLTYPE loc = this->get_location();
+
+                 _mesa_glsl_error(& loc, state,
+                                  "function `%s' parameter `%s' qualifiers "
+                                  "don't match prototype",
+                                  name, a->name);
+              }
+
+              iter_a.next();
+              iter_b.next();
+           }
 
-           if (is_definition && (sig->definition != NULL)) {
+           if (sig->return_type != return_type) {
+              YYLTYPE loc = this->get_location();
+
+              _mesa_glsl_error(& loc, state,
+                               "function `%s' return type doesn't match "
+                               "prototype",
+                               name);
+           }
+
+           if (is_definition && sig->is_defined) {
               YYLTYPE loc = this->get_location();
 
               _mesa_glsl_error(& loc, state, "function `%s' redefined", name);
@@ -1866,6 +2007,9 @@ ast_function::hir(exec_list *instructions,
    } else {
       f = new ir_function(name);
       state->symbols->add_function(f->name, f);
+
+      /* Emit the new function header */
+      instructions->push_tail(f);
    }
 
    /* Verify the return type of main() */
@@ -1922,12 +2066,6 @@ ast_function_definition::hir(exec_list *instructions,
    assert(state->current_function == NULL);
    state->current_function = signature;
 
-   ir_label *label = new ir_label(signature->function_name(), signature);
-   if (signature->definition == NULL) {
-      signature->definition = label;
-   }
-   instructions->push_tail(label);
-
    /* Duplicate parameters declared in the prototype as concrete variables.
     * Add these to the symbol table.
     */
@@ -1949,11 +2087,9 @@ ast_function_definition::hir(exec_list *instructions,
       }
    }
 
-   /* Convert the body of the function to HIR, and append the resulting
-    * instructions to the list that currently consists of the function label
-    * and the function parameters.
-    */
+   /* Convert the body of the function to HIR. */
    this->body->hir(&signature->body, state);
+   signature->is_defined = true;
 
    state->symbols->pop_scope();
 
@@ -1984,7 +2120,7 @@ ast_jump_statement::hir(exec_list *instructions,
            _mesa_glsl_error(& loc, state,
                             "`return` with a value, in function `%s' "
                             "returning void",
-                            state->current_function->definition->label);
+                            state->current_function->function_name());
         }
 
         ir_expression *const ret = (ir_expression *)
@@ -2004,7 +2140,7 @@ ast_jump_statement::hir(exec_list *instructions,
            _mesa_glsl_error(& loc, state,
                             "`return' with no value, in function %s returning "
                             "non-void",
-                            state->current_function->definition->label);
+                            state->current_function->function_name());
         }
         inst = new ir_return;
       }
@@ -2146,9 +2282,9 @@ ir_rvalue *
 ast_iteration_statement::hir(exec_list *instructions,
                             struct _mesa_glsl_parse_state *state)
 {
-   /* For loops start a new scope, but while and do-while loops do not.
+   /* For-loops and while-loops start a new scope, but do-while loops do not.
     */
-   if (mode == ast_for)
+   if (mode != ast_do_while)
       state->symbols->push_scope();
 
    if (init_statement != NULL)
@@ -2179,7 +2315,7 @@ ast_iteration_statement::hir(exec_list *instructions,
    if (mode == ast_do_while)
       condition_to_hir(stmt, state);
 
-   if (mode == ast_for)
+   if (mode != ast_do_while)
       state->symbols->pop_scope();
 
    /* Restore previous nesting before returning.