mesa: set up gl_vert_result and gl_frag_attrib values for gl_ClipDistance.
[mesa.git] / src / glsl / ir_constant_expression.cpp
index ec0e26de185a0e1c6c6199c7eedf89df65f70e6f..f0299a2c4a0bfe5c11a095811c17935cbe5d10b0 100644 (file)
@@ -54,7 +54,10 @@ dot(ir_constant *op0, ir_constant *op1)
 ir_constant *
 ir_expression::constant_expression_value()
 {
-   ir_constant *op[2] = { NULL, NULL };
+   if (this->type->is_error())
+      return NULL;
+
+   ir_constant *op[Elements(this->operands)] = { NULL, };
    ir_constant_data data;
 
    memset(&data, 0, sizeof(data));
@@ -83,7 +86,7 @@ ir_expression::constant_expression_value()
       components = op[1]->type->components();
    }
 
-   void *ctx = talloc_parent(this);
+   void *ctx = ralloc_parent(this);
 
    /* Handle array operations here, rather than below. */
    if (op[0]->type->is_array()) {
@@ -100,6 +103,21 @@ ir_expression::constant_expression_value()
    }
 
    switch (this->operation) {
+   case ir_unop_bit_not:
+       switch (op[0]->type->base_type) {
+       case GLSL_TYPE_INT:
+           for (unsigned c = 0; c < components; c++)
+               data.i[c] = ~ op[0]->value.i[c];
+           break;
+       case GLSL_TYPE_UINT:
+           for (unsigned c = 0; c < components; c++)
+               data.u[c] = ~ op[0]->value.u[c];
+           break;
+       default:
+           assert(0);
+       }
+       break;
+
    case ir_unop_logic_not:
       assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
       for (unsigned c = 0; c < op[0]->type->components(); c++)
@@ -109,31 +127,31 @@ ir_expression::constant_expression_value()
    case ir_unop_f2i:
       assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
-        data.i[c] = op[0]->value.f[c];
+        data.i[c] = (int) op[0]->value.f[c];
       }
       break;
    case ir_unop_i2f:
       assert(op[0]->type->base_type == GLSL_TYPE_INT);
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
-        data.f[c] = op[0]->value.i[c];
+        data.f[c] = (float) op[0]->value.i[c];
       }
       break;
    case ir_unop_u2f:
       assert(op[0]->type->base_type == GLSL_TYPE_UINT);
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
-        data.f[c] = op[0]->value.u[c];
+        data.f[c] = (float) op[0]->value.u[c];
       }
       break;
    case ir_unop_b2f:
       assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
-        data.f[c] = op[0]->value.b[c] ? 1.0 : 0.0;
+        data.f[c] = op[0]->value.b[c] ? 1.0F : 0.0F;
       }
       break;
    case ir_unop_f2b:
       assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
-        data.b[c] = bool(op[0]->value.f[c]);
+        data.b[c] = op[0]->value.f[c] != 0.0F ? true : false;
       }
       break;
    case ir_unop_b2i:
@@ -145,10 +163,21 @@ ir_expression::constant_expression_value()
    case ir_unop_i2b:
       assert(op[0]->type->is_integer());
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
-        data.b[c] = bool(op[0]->value.u[c]);
+        data.b[c] = op[0]->value.u[c] ? true : false;
+      }
+      break;
+   case ir_unop_u2i:
+      assert(op[0]->type->base_type == GLSL_TYPE_UINT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.i[c] = op[0]->value.u[c];
+      }
+      break;
+   case ir_unop_i2u:
+      assert(op[0]->type->base_type == GLSL_TYPE_INT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.u[c] = op[0]->value.i[c];
       }
       break;
-
    case ir_unop_any:
       assert(op[0]->type->is_boolean());
       data.b[0] = false;
@@ -198,6 +227,7 @@ ir_expression::constant_expression_value()
       break;
 
    case ir_unop_sin:
+   case ir_unop_sin_reduced:
       assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
         data.f[c] = sinf(op[0]->value.f[c]);
@@ -205,6 +235,7 @@ ir_expression::constant_expression_value()
       break;
 
    case ir_unop_cos:
+   case ir_unop_cos_reduced:
       assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
         data.f[c] = cosf(op[0]->value.f[c]);
@@ -215,7 +246,7 @@ ir_expression::constant_expression_value()
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
         switch (this->type->base_type) {
         case GLSL_TYPE_UINT:
-           data.u[c] = -op[0]->value.u[c];
+           data.u[c] = -((int) op[0]->value.u[c]);
            break;
         case GLSL_TYPE_INT:
            data.i[c] = -op[0]->value.i[c];
@@ -281,7 +312,7 @@ ir_expression::constant_expression_value()
            break;
         case GLSL_TYPE_FLOAT:
            if (op[0]->value.f[c] != 0.0)
-              data.f[c] = 1.0 / op[0]->value.f[c];
+              data.f[c] = 1.0F / op[0]->value.f[c];
            break;
         default:
            assert(0);
@@ -292,7 +323,7 @@ ir_expression::constant_expression_value()
    case ir_unop_rsq:
       assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
-        data.f[c] = 1.0 / sqrtf(op[0]->value.f[c]);
+        data.f[c] = 1.0F / sqrtf(op[0]->value.f[c]);
       }
       break;
 
@@ -394,17 +425,6 @@ ir_expression::constant_expression_value()
       }
       break;
 
-   case ir_binop_cross:
-      assert(op[0]->type == glsl_type::vec3_type);
-      assert(op[1]->type == glsl_type::vec3_type);
-      data.f[0] = (op[0]->value.f[1] * op[1]->value.f[2] -
-                  op[1]->value.f[1] * op[0]->value.f[2]);
-      data.f[1] = (op[0]->value.f[2] * op[1]->value.f[0] -
-                  op[1]->value.f[2] * op[0]->value.f[0]);
-      data.f[2] = (op[0]->value.f[0] * op[1]->value.f[1] -
-                  op[1]->value.f[0] * op[0]->value.f[1]);
-      break;
-
    case ir_binop_add:
       assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
       for (unsigned c = 0, c0 = 0, c1 = 0;
@@ -498,6 +518,7 @@ ir_expression::constant_expression_value()
 
       break;
    case ir_binop_div:
+      /* FINISHME: Emit warning when division-by-zero is detected. */
       assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
       for (unsigned c = 0, c0 = 0, c1 = 0;
           c < components;
@@ -505,10 +526,18 @@ ir_expression::constant_expression_value()
 
         switch (op[0]->type->base_type) {
         case GLSL_TYPE_UINT:
-           data.u[c] = op[0]->value.u[c0] / op[1]->value.u[c1];
+           if (op[1]->value.u[c1] == 0) {
+              data.u[c] = 0;
+           } else {
+              data.u[c] = op[0]->value.u[c0] / op[1]->value.u[c1];
+           }
            break;
         case GLSL_TYPE_INT:
-           data.i[c] = op[0]->value.i[c0] / op[1]->value.i[c1];
+           if (op[1]->value.i[c1] == 0) {
+              data.i[c] = 0;
+           } else {
+              data.i[c] = op[0]->value.i[c0] / op[1]->value.i[c1];
+           }
            break;
         case GLSL_TYPE_FLOAT:
            data.f[c] = op[0]->value.f[c0] / op[1]->value.f[c1];
@@ -520,6 +549,7 @@ ir_expression::constant_expression_value()
 
       break;
    case ir_binop_mod:
+      /* FINISHME: Emit warning when division-by-zero is detected. */
       assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
       for (unsigned c = 0, c0 = 0, c1 = 0;
           c < components;
@@ -527,10 +557,18 @@ ir_expression::constant_expression_value()
 
         switch (op[0]->type->base_type) {
         case GLSL_TYPE_UINT:
-           data.u[c] = op[0]->value.u[c0] % op[1]->value.u[c1];
+           if (op[1]->value.u[c1] == 0) {
+              data.u[c] = 0;
+           } else {
+              data.u[c] = op[0]->value.u[c0] % op[1]->value.u[c1];
+           }
            break;
         case GLSL_TYPE_INT:
-           data.i[c] = op[0]->value.i[c0] % op[1]->value.i[c1];
+           if (op[1]->value.i[c1] == 0) {
+              data.i[c] = 0;
+           } else {
+              data.i[c] = op[0]->value.i[c0] % op[1]->value.i[c1];
+           }
            break;
         case GLSL_TYPE_FLOAT:
            /* We don't use fmod because it rounds toward zero; GLSL specifies
@@ -563,96 +601,113 @@ ir_expression::constant_expression_value()
       break;
 
    case ir_binop_less:
-      switch (op[0]->type->base_type) {
-      case GLSL_TYPE_UINT:
-        data.b[0] = op[0]->value.u[0] < op[1]->value.u[0];
-        break;
-      case GLSL_TYPE_INT:
-        data.b[0] = op[0]->value.i[0] < op[1]->value.i[0];
-        break;
-      case GLSL_TYPE_FLOAT:
-        data.b[0] = op[0]->value.f[0] < op[1]->value.f[0];
-        break;
-      default:
-        assert(0);
+      assert(op[0]->type == op[1]->type);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[0] = op[0]->value.u[0] < op[1]->value.u[0];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[0] = op[0]->value.i[0] < op[1]->value.i[0];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[0] = op[0]->value.f[0] < op[1]->value.f[0];
+           break;
+        default:
+           assert(0);
+        }
       }
       break;
    case ir_binop_greater:
-      switch (op[0]->type->base_type) {
-      case GLSL_TYPE_UINT:
-        data.b[0] = op[0]->value.u[0] > op[1]->value.u[0];
-        break;
-      case GLSL_TYPE_INT:
-        data.b[0] = op[0]->value.i[0] > op[1]->value.i[0];
-        break;
-      case GLSL_TYPE_FLOAT:
-        data.b[0] = op[0]->value.f[0] > op[1]->value.f[0];
-        break;
-      default:
-        assert(0);
+      assert(op[0]->type == op[1]->type);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[c] = op[0]->value.u[c] > op[1]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[c] = op[0]->value.i[c] > op[1]->value.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[c] = op[0]->value.f[c] > op[1]->value.f[c];
+           break;
+        default:
+           assert(0);
+        }
       }
       break;
    case ir_binop_lequal:
-      switch (op[0]->type->base_type) {
-      case GLSL_TYPE_UINT:
-        data.b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
-        break;
-      case GLSL_TYPE_INT:
-        data.b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
-        break;
-      case GLSL_TYPE_FLOAT:
-        data.b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
-        break;
-      default:
-        assert(0);
+      assert(op[0]->type == op[1]->type);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
+           break;
+        default:
+           assert(0);
+        }
       }
       break;
    case ir_binop_gequal:
-      switch (op[0]->type->base_type) {
-      case GLSL_TYPE_UINT:
-        data.b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
-        break;
-      case GLSL_TYPE_INT:
-        data.b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
-        break;
-      case GLSL_TYPE_FLOAT:
-        data.b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
-        break;
-      default:
-        assert(0);
+      assert(op[0]->type == op[1]->type);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
+           break;
+        default:
+           assert(0);
+        }
       }
       break;
    case ir_binop_equal:
-      switch (op[0]->type->base_type) {
-      case GLSL_TYPE_UINT:
-         data.b[0] = op[0]->value.u[0] == op[1]->value.u[0];
-         break;
-      case GLSL_TYPE_INT:
-         data.b[0] = op[0]->value.i[0] == op[1]->value.i[0];
-         break;
-      case GLSL_TYPE_FLOAT:
-         data.b[0] = op[0]->value.f[0] == op[1]->value.f[0];
-         break;
-      default:
-         assert(0);
+      assert(op[0]->type == op[1]->type);
+      for (unsigned c = 0; c < components; c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[c] = op[0]->value.u[c] == op[1]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[c] = op[0]->value.i[c] == op[1]->value.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[c] = op[0]->value.f[c] == op[1]->value.f[c];
+           break;
+        default:
+           assert(0);
+        }
       }
       break;
    case ir_binop_nequal:
-      switch (op[0]->type->base_type) {
-      case GLSL_TYPE_UINT:
-         data.b[0] = op[0]->value.u[0] != op[1]->value.u[0];
-         break;
-      case GLSL_TYPE_INT:
-         data.b[0] = op[0]->value.i[0] != op[1]->value.i[0];
-         break;
-      case GLSL_TYPE_FLOAT:
-         data.b[0] = op[0]->value.f[0] != op[1]->value.f[0];
-         break;
-      default:
-         assert(0);
+      assert(op[0]->type != op[1]->type);
+      for (unsigned c = 0; c < components; c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[c] = op[0]->value.u[c] != op[1]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[c] = op[0]->value.i[c] != op[1]->value.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[c] = op[0]->value.f[c] != op[1]->value.f[c];
+           break;
+        default:
+           assert(0);
+        }
       }
       break;
-
    case ir_binop_all_equal:
       data.b[0] = op[0]->has_value(op[1]);
       break;
@@ -660,6 +715,126 @@ ir_expression::constant_expression_value()
       data.b[0] = !op[0]->has_value(op[1]);
       break;
 
+   case ir_binop_lshift:
+      for (unsigned c = 0, c0 = 0, c1 = 0;
+           c < components;
+           c0 += c0_inc, c1 += c1_inc, c++) {
+
+          if (op[0]->type->base_type == GLSL_TYPE_INT &&
+              op[1]->type->base_type == GLSL_TYPE_INT) {
+              data.i[c] = op[0]->value.i[c0] << op[1]->value.i[c1];
+
+          } else if (op[0]->type->base_type == GLSL_TYPE_INT &&
+                     op[1]->type->base_type == GLSL_TYPE_UINT) {
+              data.i[c] = op[0]->value.i[c0] << op[1]->value.u[c1];
+
+          } else if (op[0]->type->base_type == GLSL_TYPE_UINT &&
+                     op[1]->type->base_type == GLSL_TYPE_INT) {
+              data.u[c] = op[0]->value.u[c0] << op[1]->value.i[c1];
+
+          } else if (op[0]->type->base_type == GLSL_TYPE_UINT &&
+                     op[1]->type->base_type == GLSL_TYPE_UINT) {
+              data.u[c] = op[0]->value.u[c0] << op[1]->value.u[c1];
+          }
+      }
+      break;
+
+   case ir_binop_rshift:
+       for (unsigned c = 0, c0 = 0, c1 = 0;
+            c < components;
+            c0 += c0_inc, c1 += c1_inc, c++) {
+
+           if (op[0]->type->base_type == GLSL_TYPE_INT &&
+               op[1]->type->base_type == GLSL_TYPE_INT) {
+               data.i[c] = op[0]->value.i[c0] >> op[1]->value.i[c1];
+
+           } else if (op[0]->type->base_type == GLSL_TYPE_INT &&
+                      op[1]->type->base_type == GLSL_TYPE_UINT) {
+               data.i[c] = op[0]->value.i[c0] >> op[1]->value.u[c1];
+
+           } else if (op[0]->type->base_type == GLSL_TYPE_UINT &&
+                      op[1]->type->base_type == GLSL_TYPE_INT) {
+               data.u[c] = op[0]->value.u[c0] >> op[1]->value.i[c1];
+
+           } else if (op[0]->type->base_type == GLSL_TYPE_UINT &&
+                      op[1]->type->base_type == GLSL_TYPE_UINT) {
+               data.u[c] = op[0]->value.u[c0] >> op[1]->value.u[c1];
+           }
+       }
+       break;
+
+   case ir_binop_bit_and:
+      for (unsigned c = 0, c0 = 0, c1 = 0;
+           c < components;
+           c0 += c0_inc, c1 += c1_inc, c++) {
+
+          switch (op[0]->type->base_type) {
+          case GLSL_TYPE_INT:
+              data.i[c] = op[0]->value.i[c0] & op[1]->value.i[c1];
+              break;
+          case GLSL_TYPE_UINT:
+              data.u[c] = op[0]->value.u[c0] & op[1]->value.u[c1];
+              break;
+          default:
+              assert(0);
+          }
+      }
+      break;
+
+   case ir_binop_bit_or:
+      for (unsigned c = 0, c0 = 0, c1 = 0;
+           c < components;
+           c0 += c0_inc, c1 += c1_inc, c++) {
+
+          switch (op[0]->type->base_type) {
+          case GLSL_TYPE_INT:
+              data.i[c] = op[0]->value.i[c0] | op[1]->value.i[c1];
+              break;
+          case GLSL_TYPE_UINT:
+              data.u[c] = op[0]->value.u[c0] | op[1]->value.u[c1];
+              break;
+          default:
+              assert(0);
+          }
+      }
+      break;
+
+   case ir_binop_bit_xor:
+      for (unsigned c = 0, c0 = 0, c1 = 0;
+           c < components;
+           c0 += c0_inc, c1 += c1_inc, c++) {
+
+          switch (op[0]->type->base_type) {
+          case GLSL_TYPE_INT:
+              data.i[c] = op[0]->value.i[c0] ^ op[1]->value.i[c1];
+              break;
+          case GLSL_TYPE_UINT:
+              data.u[c] = op[0]->value.u[c0] ^ op[1]->value.u[c1];
+              break;
+          default:
+              assert(0);
+          }
+      }
+      break;
+
+   case ir_quadop_vector:
+      for (unsigned c = 0; c < this->type->vector_elements; c++) {
+        switch (this->type->base_type) {
+        case GLSL_TYPE_INT:
+           data.i[c] = op[c]->value.i[0];
+           break;
+        case GLSL_TYPE_UINT:
+           data.u[c] = op[c]->value.u[0];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.f[c] = op[c]->value.f[0];
+           break;
+        default:
+           assert(0);
+        }
+      }
+      break;
+
    default:
       /* FINISHME: Should handle all expression types. */
       return NULL;
@@ -699,7 +874,7 @@ ir_swizzle::constant_expression_value()
         }
       }
 
-      void *ctx = talloc_parent(this);
+      void *ctx = ralloc_parent(this);
       return new(ctx) ir_constant(this->type, &data);
    }
    return NULL;
@@ -722,7 +897,7 @@ ir_dereference_variable::constant_expression_value()
    if (!var->constant_value)
       return NULL;
 
-   return var->constant_value->clone(talloc_parent(var), NULL);
+   return var->constant_value->clone(ralloc_parent(var), NULL);
 }
 
 
@@ -733,7 +908,7 @@ ir_dereference_array::constant_expression_value()
    ir_constant *idx = this->array_index->constant_expression_value();
 
    if ((array != NULL) && (idx != NULL)) {
-      void *ctx = talloc_parent(this);
+      void *ctx = ralloc_parent(this);
       if (array->type->is_matrix()) {
         /* Array access of a matrix results in a vector.
          */
@@ -746,7 +921,7 @@ ir_dereference_array::constant_expression_value()
          */
         const unsigned mat_idx = column * column_type->vector_elements;
 
-        ir_constant_data data;
+        ir_constant_data data = { { 0 } };
 
         switch (column_type->base_type) {
         case GLSL_TYPE_UINT:
@@ -838,7 +1013,7 @@ ir_call::constant_expression_value()
     * - Fill "data" with appopriate constant data
     * - Return an ir_constant directly.
     */
-   void *mem_ctx = talloc_parent(this);
+   void *mem_ctx = ralloc_parent(this);
    ir_expression *expr = NULL;
 
    ir_constant_data data;
@@ -865,10 +1040,18 @@ ir_call::constant_expression_value()
       assert(op[0]->type->is_float());
       for (unsigned c = 0; c < op[0]->type->components(); c++)
         data.f[c] = acosf(op[0]->value.f[c]);
+   } else if (strcmp(callee, "acosh") == 0) {
+      assert(op[0]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = acoshf(op[0]->value.f[c]);
    } else if (strcmp(callee, "asin") == 0) {
       assert(op[0]->type->is_float());
       for (unsigned c = 0; c < op[0]->type->components(); c++)
         data.f[c] = asinf(op[0]->value.f[c]);
+   } else if (strcmp(callee, "asinh") == 0) {
+      assert(op[0]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = asinhf(op[0]->value.f[c]);
    } else if (strcmp(callee, "atan") == 0) {
       assert(op[0]->type->is_float());
       if (num_parameters == 2) {
@@ -879,6 +1062,10 @@ ir_call::constant_expression_value()
         for (unsigned c = 0; c < op[0]->type->components(); c++)
            data.f[c] = atanf(op[0]->value.f[c]);
       }
+   } else if (strcmp(callee, "atanh") == 0) {
+      assert(op[0]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = atanhf(op[0]->value.f[c]);
    } else if (strcmp(callee, "dFdx") == 0 || strcmp(callee, "dFdy") == 0) {
       return ir_constant::zero(mem_ctx, this->type);
    } else if (strcmp(callee, "ceil") == 0) {
@@ -915,11 +1102,18 @@ ir_call::constant_expression_value()
       for (unsigned c = 0; c < op[0]->type->components(); c++)
         data.f[c] = coshf(op[0]->value.f[c]);
    } else if (strcmp(callee, "cross") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_binop_cross, type, op[0], op[1]);
+      assert(op[0]->type == glsl_type::vec3_type);
+      assert(op[1]->type == glsl_type::vec3_type);
+      data.f[0] = (op[0]->value.f[1] * op[1]->value.f[2] -
+                  op[1]->value.f[1] * op[0]->value.f[2]);
+      data.f[1] = (op[0]->value.f[2] * op[1]->value.f[0] -
+                  op[1]->value.f[2] * op[0]->value.f[0]);
+      data.f[2] = (op[0]->value.f[0] * op[1]->value.f[1] -
+                  op[1]->value.f[0] * op[0]->value.f[1]);
    } else if (strcmp(callee, "degrees") == 0) {
       assert(op[0]->type->is_float());
       for (unsigned c = 0; c < op[0]->type->components(); c++)
-        data.f[c] = 180.0/M_PI * op[0]->value.f[c];
+        data.f[c] = 180.0F / M_PI * op[0]->value.f[c];
    } else if (strcmp(callee, "distance") == 0) {
       assert(op[0]->type->is_float() && op[1]->type->is_float());
       float length_squared = 0.0;
@@ -1110,7 +1304,7 @@ ir_call::constant_expression_value()
    } else if (strcmp(callee, "radians") == 0) {
       assert(op[0]->type->is_float());
       for (unsigned c = 0; c < op[0]->type->components(); c++)
-        data.f[c] = M_PI/180.0 * op[0]->value.f[c];
+        data.f[c] = M_PI / 180.0F * op[0]->value.f[c];
    } else if (strcmp(callee, "reflect") == 0) {
       assert(op[0]->type->is_float());
       float dot_NI = dot(op[1], op[0]);
@@ -1119,7 +1313,7 @@ ir_call::constant_expression_value()
    } else if (strcmp(callee, "refract") == 0) {
       const float eta = op[2]->value.f[0];
       const float dot_NI = dot(op[1], op[0]);
-      const float k = 1.0 - eta * eta * (1.0 - dot_NI * dot_NI);
+      const float k = 1.0F - eta * eta * (1.0F - dot_NI * dot_NI);
       if (k < 0.0) {
         return ir_constant::zero(mem_ctx, this->type);
       } else {
@@ -1159,7 +1353,7 @@ ir_call::constant_expression_value()
       /* op[0] (edge) may be either a scalar or a vector */
       const unsigned c0_inc = op[0]->type->is_scalar() ? 0 : 1;
       for (unsigned c = 0, c0 = 0; c < type->components(); c0 += c0_inc, c++)
-        data.f[c] = (op[1]->value.f[c] < op[0]->value.f[c0]) ? 0.0 : 1.0;
+        data.f[c] = (op[1]->value.f[c] < op[0]->value.f[c0]) ? 0.0F : 1.0F;
    } else if (strcmp(callee, "tan") == 0) {
       assert(op[0]->type->is_float());
       for (unsigned c = 0; c < op[0]->type->components(); c++)