glsl/ast/ir: Add 64-bit integer constant support
authorDave Airlie <airlied@redhat.com>
Wed, 8 Jun 2016 23:39:48 +0000 (09:39 +1000)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 20 Jan 2017 23:41:23 +0000 (15:41 -0800)
This adds support for 64-bit integer constants to the parser,
ast and ir.

v2: fix a few issues found in testing.

v3: Add missing ir_constant copy contructor support.

v4: Use PRIu64 and PRId64 in printfs in glsl_parser_extras.cpp.
Suggested by Nicolai.  Rebase on Marek's linalloc changes.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> [v2]
Reviewed-by: Matt Turner <mattst88@gmail.com> [v3]
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/compiler/glsl/ast.h
src/compiler/glsl/ast_function.cpp
src/compiler/glsl/ast_to_hir.cpp
src/compiler/glsl/glsl_lexer.ll
src/compiler/glsl/glsl_parser.yy
src/compiler/glsl/glsl_parser_extras.cpp
src/compiler/glsl/ir.cpp
src/compiler/glsl/ir.h

index e3f629e..3dff164 100644 (file)
@@ -195,6 +195,8 @@ enum ast_operators {
    ast_float_constant,
    ast_bool_constant,
    ast_double_constant,
+   ast_int64_constant,
+   ast_uint64_constant,
 
    ast_sequence,
    ast_aggregate
@@ -255,6 +257,8 @@ public:
       unsigned uint_constant;
       int bool_constant;
       double double_constant;
+      uint64_t uint64_constant;
+      int64_t int64_constant;
    } primary_expression;
 
 
index 3f353a3..3265712 100644 (file)
@@ -1260,6 +1260,12 @@ emit_inline_vector_constructor(const glsl_type *type,
                case GLSL_TYPE_BOOL:
                   data.b[i + base_component] = c->get_bool_component(i);
                   break;
+               case GLSL_TYPE_UINT64:
+                  data.u64[i + base_component] = c->get_uint64_component(i);
+                  break;
+               case GLSL_TYPE_INT64:
+                  data.i64[i + base_component] = c->get_int64_component(i);
+                  break;
                default:
                   assert(!"Should not get here.");
                   break;
@@ -1267,8 +1273,7 @@ emit_inline_vector_constructor(const glsl_type *type,
             }
 
             /* Mask of fields to be written in the assignment. */
-            constant_mask |=
-               ((1U << rhs_components) - 1) << base_lhs_component;
+            constant_mask |= ((1U << rhs_components) - 1) << base_lhs_component;
             constant_components += rhs_components;
 
             base_component += rhs_components;
index 5cd094d..b52a397 100644 (file)
@@ -1258,6 +1258,10 @@ constant_one_for_inc_dec(void *ctx, const glsl_type *type)
       return new(ctx) ir_constant((unsigned) 1);
    case GLSL_TYPE_INT:
       return new(ctx) ir_constant(1);
+   case GLSL_TYPE_UINT64:
+      return new(ctx) ir_constant((uint64_t) 1);
+   case GLSL_TYPE_INT64:
+      return new(ctx) ir_constant((int64_t) 1);
    default:
    case GLSL_TYPE_FLOAT:
       return new(ctx) ir_constant(1.0f);
@@ -2008,6 +2012,14 @@ ast_expression::do_hir(exec_list *instructions,
       result = new(ctx) ir_constant(this->primary_expression.double_constant);
       break;
 
+   case ast_uint64_constant:
+      result = new(ctx) ir_constant(this->primary_expression.uint64_constant);
+      break;
+
+   case ast_int64_constant:
+      result = new(ctx) ir_constant(this->primary_expression.int64_constant);
+      break;
+
    case ast_sequence: {
       /* It should not be possible to generate a sequence in the AST without
        * any expressions in it.
@@ -2134,6 +2146,8 @@ ast_expression::has_sequence_subexpression() const
    case ast_float_constant:
    case ast_bool_constant:
    case ast_double_constant:
+   case ast_int64_constant:
+   case ast_uint64_constant:
       return false;
 
    case ast_aggregate:
index 4c0980f..039eb43 100644 (file)
@@ -107,17 +107,29 @@ literal_integer(char *text, int len, struct _mesa_glsl_parse_state *state,
 {
    bool is_uint = (text[len - 1] == 'u' ||
                   text[len - 1] == 'U');
+   bool is_long = (text[len - 1] == 'l' || text[len - 1] == 'L');
    const char *digits = text;
 
+   if (is_long)
+      is_uint = (text[len - 2] == 'u' && text[len - 1] == 'l') ||
+                (text[len - 2] == 'U' && text[len - 1] == 'L');
    /* Skip "0x" */
    if (base == 16)
       digits += 2;
 
    unsigned long long value = strtoull(digits, NULL, base);
 
-   lval->n = (int)value;
+   if (is_long)
+      lval->n64 = (int64_t)value;
+   else
+      lval->n = (int)value;
 
-   if (value > UINT_MAX) {
+   if (is_long && !is_uint && base == 10 && value > (uint64_t)LLONG_MAX + 1) {
+      /* Tries to catch unintentionally providing a negative value. */
+      _mesa_glsl_warning(lloc, state,
+                         "signed literal value `%s' is interpreted as %lld",
+                         text, lval->n64);
+   } else if (!is_long && value > UINT_MAX) {
       /* Note that signed 0xffffffff is valid, not out of range! */
       if (state->is_version(130, 300)) {
         _mesa_glsl_error(lloc, state,
@@ -135,7 +147,10 @@ literal_integer(char *text, int len, struct _mesa_glsl_parse_state *state,
                         "signed literal value `%s' is interpreted as %d",
                         text, lval->n);
    }
-   return is_uint ? UINTCONSTANT : INTCONSTANT;
+   if (is_long)
+      return is_uint ? UINT64CONSTANT : INT64CONSTANT;
+   else
+      return is_uint ? UINTCONSTANT : INTCONSTANT;
 }
 
 #define LITERAL_INTEGER(base) \
@@ -462,13 +477,13 @@ layout            {
 \|=            return OR_ASSIGN;
 -=             return SUB_ASSIGN;
 
-[1-9][0-9]*[uU]?       {
+[1-9][0-9]*([uU]|[lL]|ul|UL)?  {
                            return LITERAL_INTEGER(10);
                        }
-0[xX][0-9a-fA-F]+[uU]? {
+0[xX][0-9a-fA-F]+([uU]|[lL]|ul|UL)?    {
                            return LITERAL_INTEGER(16);
                        }
-0[0-7]*[uU]?           {
+0[0-7]*([uU]|[lL]|ul|UL)?              {
                            return LITERAL_INTEGER(8);
                        }
 
index 734dc49..8526074 100644 (file)
@@ -97,6 +97,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
 
 %union {
    int n;
+   int64_t n64;
    float real;
    double dreal;
    const char *identifier;
@@ -174,6 +175,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
 %token <real> FLOATCONSTANT
 %token <dreal> DOUBLECONSTANT
 %token <n> INTCONSTANT UINTCONSTANT BOOLCONSTANT
+%token <n64> INT64CONSTANT UINT64CONSTANT
 %token <identifier> FIELD_SELECTION
 %token LEFT_OP RIGHT_OP
 %token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
@@ -452,6 +454,20 @@ primary_expression:
       $$->set_location(@1);
       $$->primary_expression.uint_constant = $1;
    }
+   | INT64CONSTANT
+   {
+      void *ctx = state->linalloc;
+      $$ = new(ctx) ast_expression(ast_int64_constant, NULL, NULL, NULL);
+      $$->set_location(@1);
+      $$->primary_expression.int64_constant = $1;
+   }
+   | UINT64CONSTANT
+   {
+      void *ctx = state->linalloc;
+      $$ = new(ctx) ast_expression(ast_uint64_constant, NULL, NULL, NULL);
+      $$->set_location(@1);
+      $$->primary_expression.uint64_constant = $1;
+   }
    | FLOATCONSTANT
    {
       void *ctx = state->linalloc;
index 26251ec..f542ce7 100644 (file)
@@ -1248,6 +1248,14 @@ ast_expression::print(void) const
       printf("%f ", primary_expression.double_constant);
       break;
 
+   case ast_int64_constant:
+      printf("%" PRId64 " ", primary_expression.int64_constant);
+      break;
+
+   case ast_uint64_constant:
+      printf("%" PRIu64 " ", primary_expression.uint64_constant);
+      break;
+
    case ast_bool_constant:
       printf("%s ",
             primary_expression.bool_constant
index 8e4b382..ad88ada 100644 (file)
@@ -613,6 +613,32 @@ ir_constant::ir_constant(int integer, unsigned vector_elements)
    }
 }
 
+ir_constant::ir_constant(uint64_t u64, unsigned vector_elements)
+   : ir_rvalue(ir_type_constant)
+{
+   assert(vector_elements <= 4);
+   this->type = glsl_type::get_instance(GLSL_TYPE_UINT64, vector_elements, 1);
+   for (unsigned i = 0; i < vector_elements; i++) {
+      this->value.u64[i] = u64;
+   }
+   for (unsigned i = vector_elements; i < 16; i++) {
+      this->value.u64[i] = 0;
+   }
+}
+
+ir_constant::ir_constant(int64_t int64, unsigned vector_elements)
+   : ir_rvalue(ir_type_constant)
+{
+   assert(vector_elements <= 4);
+   this->type = glsl_type::get_instance(GLSL_TYPE_INT64, vector_elements, 1);
+   for (unsigned i = 0; i < vector_elements; i++) {
+      this->value.i64[i] = int64;
+   }
+   for (unsigned i = vector_elements; i < 16; i++) {
+      this->value.i64[i] = 0;
+   }
+}
+
 ir_constant::ir_constant(bool b, unsigned vector_elements)
    : ir_rvalue(ir_type_constant)
 {
@@ -716,6 +742,11 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
            for (unsigned i = 0; i < type->components(); i++)
               this->value.d[i] = value->value.d[0];
            break;
+        case GLSL_TYPE_UINT64:
+        case GLSL_TYPE_INT64:
+           for (unsigned i = 0; i < type->components(); i++)
+              this->value.u64[i] = value->value.u64[0];
+           break;
         case GLSL_TYPE_BOOL:
            for (unsigned i = 0; i < type->components(); i++)
               this->value.b[i] = value->value.b[0];
@@ -778,6 +809,12 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
         case GLSL_TYPE_DOUBLE:
            this->value.d[i] = value->get_double_component(j);
            break;
+         case GLSL_TYPE_UINT64:
+           this->value.u64[i] = value->get_uint64_component(j);
+           break;
+        case GLSL_TYPE_INT64:
+           this->value.i64[i] = value->get_int64_component(j);
+           break;
         default:
            /* FINISHME: What to do?  Exceptions are not the answer.
             */
@@ -831,6 +868,8 @@ ir_constant::get_bool_component(unsigned i) const
    case GLSL_TYPE_FLOAT: return ((int)this->value.f[i]) != 0;
    case GLSL_TYPE_BOOL:  return this->value.b[i];
    case GLSL_TYPE_DOUBLE: return this->value.d[i] != 0.0;
+   case GLSL_TYPE_UINT64: return this->value.u64[i] != 0;
+   case GLSL_TYPE_INT64:  return this->value.i64[i] != 0;
    default:              assert(!"Should not get here."); break;
    }
 
@@ -849,6 +888,8 @@ ir_constant::get_float_component(unsigned i) const
    case GLSL_TYPE_FLOAT: return this->value.f[i];
    case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1.0f : 0.0f;
    case GLSL_TYPE_DOUBLE: return (float) this->value.d[i];
+   case GLSL_TYPE_UINT64: return (float) this->value.u64[i];
+   case GLSL_TYPE_INT64:  return (float) this->value.i64[i];
    default:              assert(!"Should not get here."); break;
    }
 
@@ -867,6 +908,8 @@ ir_constant::get_double_component(unsigned i) const
    case GLSL_TYPE_FLOAT: return (double) this->value.f[i];
    case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1.0 : 0.0;
    case GLSL_TYPE_DOUBLE: return this->value.d[i];
+   case GLSL_TYPE_UINT64: return (double) this->value.u64[i];
+   case GLSL_TYPE_INT64:  return (double) this->value.i64[i];
    default:              assert(!"Should not get here."); break;
    }
 
@@ -885,6 +928,8 @@ ir_constant::get_int_component(unsigned i) const
    case GLSL_TYPE_FLOAT: return (int) this->value.f[i];
    case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1 : 0;
    case GLSL_TYPE_DOUBLE: return (int) this->value.d[i];
+   case GLSL_TYPE_UINT64: return (int) this->value.u64[i];
+   case GLSL_TYPE_INT64:  return (int) this->value.i64[i];
    default:              assert(!"Should not get here."); break;
    }
 
@@ -903,6 +948,48 @@ ir_constant::get_uint_component(unsigned i) const
    case GLSL_TYPE_FLOAT: return (unsigned) this->value.f[i];
    case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1 : 0;
    case GLSL_TYPE_DOUBLE: return (unsigned) this->value.d[i];
+   case GLSL_TYPE_UINT64: return (unsigned) this->value.u64[i];
+   case GLSL_TYPE_INT64:  return (unsigned) this->value.i64[i];
+   default:              assert(!"Should not get here."); break;
+   }
+
+   /* Must return something to make the compiler happy.  This is clearly an
+    * error case.
+    */
+   return 0;
+}
+
+int64_t
+ir_constant::get_int64_component(unsigned i) const
+{
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT:  return this->value.u[i];
+   case GLSL_TYPE_INT:   return this->value.i[i];
+   case GLSL_TYPE_FLOAT: return (int64_t) this->value.f[i];
+   case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1 : 0;
+   case GLSL_TYPE_DOUBLE: return (int64_t) this->value.d[i];
+   case GLSL_TYPE_UINT64: return (int64_t) this->value.u64[i];
+   case GLSL_TYPE_INT64:  return this->value.i64[i];
+   default:              assert(!"Should not get here."); break;
+   }
+
+   /* Must return something to make the compiler happy.  This is clearly an
+    * error case.
+    */
+   return 0;
+}
+
+uint64_t
+ir_constant::get_uint64_component(unsigned i) const
+{
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT:  return this->value.u[i];
+   case GLSL_TYPE_INT:   return this->value.i[i];
+   case GLSL_TYPE_FLOAT: return (uint64_t) this->value.f[i];
+   case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1 : 0;
+   case GLSL_TYPE_DOUBLE: return (uint64_t) this->value.d[i];
+   case GLSL_TYPE_UINT64: return this->value.u64[i];
+   case GLSL_TYPE_INT64:  return (uint64_t) this->value.i64[i];
    default:              assert(!"Should not get here."); break;
    }
 
@@ -968,6 +1055,8 @@ ir_constant::copy_offset(ir_constant *src, int offset)
    case GLSL_TYPE_INT:
    case GLSL_TYPE_FLOAT:
    case GLSL_TYPE_DOUBLE:
+   case GLSL_TYPE_UINT64:
+   case GLSL_TYPE_INT64:
    case GLSL_TYPE_BOOL: {
       unsigned int size = src->type->components();
       assert (size <= this->type->components() - offset);
@@ -988,6 +1077,12 @@ ir_constant::copy_offset(ir_constant *src, int offset)
         case GLSL_TYPE_DOUBLE:
            value.d[i+offset] = src->get_double_component(i);
            break;
+         case GLSL_TYPE_UINT64:
+           value.u64[i+offset] = src->get_uint64_component(i);
+           break;
+        case GLSL_TYPE_INT64:
+           value.i64[i+offset] = src->get_int64_component(i);
+           break;
         default: // Shut up the compiler
            break;
         }
@@ -1047,6 +1142,12 @@ ir_constant::copy_masked_offset(ir_constant *src, int offset, unsigned int mask)
         case GLSL_TYPE_DOUBLE:
            value.d[i+offset] = src->get_double_component(id++);
            break;
+         case GLSL_TYPE_UINT64:
+           value.u64[i+offset] = src->get_uint64_component(id++);
+           break;
+        case GLSL_TYPE_INT64:
+           value.i64[i+offset] = src->get_int64_component(id++);
+           break;
         default:
            assert(!"Should not get here.");
            return;
@@ -1111,6 +1212,14 @@ ir_constant::has_value(const ir_constant *c) const
         if (this->value.d[i] != c->value.d[i])
            return false;
         break;
+      case GLSL_TYPE_UINT64:
+        if (this->value.u64[i] != c->value.u64[i])
+           return false;
+        break;
+      case GLSL_TYPE_INT64:
+        if (this->value.i64[i] != c->value.i64[i])
+           return false;
+        break;
       default:
         assert(!"Should not get here.");
         return false;
@@ -1152,6 +1261,14 @@ ir_constant::is_value(float f, int i) const
         if (this->value.d[c] != double(f))
            return false;
         break;
+      case GLSL_TYPE_UINT64:
+        if (this->value.u64[c] != uint64_t(i))
+           return false;
+        break;
+      case GLSL_TYPE_INT64:
+        if (this->value.i64[c] != i)
+           return false;
+        break;
       default:
         /* The only other base types are structures, arrays, and samplers.
          * Samplers cannot be constants, and the others should have been
index a11dccd..afcbe29 100644 (file)
@@ -2093,6 +2093,8 @@ union ir_constant_data {
       float f[16];
       bool b[16];
       double d[16];
+      uint64_t u64[16];
+      int64_t i64[16];
 };
 
 
@@ -2104,6 +2106,8 @@ public:
    ir_constant(int i, unsigned vector_elements=1);
    ir_constant(float f, unsigned vector_elements=1);
    ir_constant(double d, unsigned vector_elements=1);
+   ir_constant(uint64_t u64, unsigned vector_elements=1);
+   ir_constant(int64_t i64, unsigned vector_elements=1);
 
    /**
     * Construct an ir_constant from a list of ir_constant values
@@ -2154,6 +2158,8 @@ public:
    double get_double_component(unsigned i) const;
    int get_int_component(unsigned i) const;
    unsigned get_uint_component(unsigned i) const;
+   int64_t get_int64_component(unsigned i) const;
+   uint64_t get_uint64_component(unsigned i) const;
    /*@}*/
 
    ir_constant *get_array_element(unsigned i) const;