[Mesa-dev] [PATCH 06/27] glsl/ast/ir: add 64-bit integer constant support (v2)

Dave Airlie airlied at gmail.com
Mon Jun 20 05:06:52 UTC 2016


From: Dave Airlie <airlied at redhat.com>

This adds support for 64-bit integer constants to the parser,
ast and ir.

v2: fix a few issues found in testing.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/compiler/glsl/ast.h                  |   4 ++
 src/compiler/glsl/ast_function.cpp       |   8 ++-
 src/compiler/glsl/ast_to_hir.cpp         |  14 ++++
 src/compiler/glsl/glsl_lexer.ll          |  27 ++++++--
 src/compiler/glsl/glsl_parser.yy         |  16 +++++
 src/compiler/glsl/glsl_parser_extras.cpp |   8 +++
 src/compiler/glsl/ir.cpp                 | 112 +++++++++++++++++++++++++++++++
 src/compiler/glsl/ir.h                   |   6 ++
 8 files changed, 188 insertions(+), 7 deletions(-)

diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h
index 06c7b03..5b4ab44 100644
--- a/src/compiler/glsl/ast.h
+++ b/src/compiler/glsl/ast.h
@@ -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
@@ -246,6 +248,8 @@ public:
       unsigned uint_constant;
       int bool_constant;
       double double_constant;
+      uint64_t uint64_constant;
+      int64_t int64_constant;
    } primary_expression;
 
 
diff --git a/src/compiler/glsl/ast_function.cpp b/src/compiler/glsl/ast_function.cpp
index f74394f..c472aae 100644
--- a/src/compiler/glsl/ast_function.cpp
+++ b/src/compiler/glsl/ast_function.cpp
@@ -1266,7 +1266,13 @@ emit_inline_vector_constructor(const glsl_type *type,
 	       case GLSL_TYPE_BOOL:
 		  data.b[i + base_component] = c->get_bool_component(i);
 		  break;
-	       default:
+               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;
 	       }
diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp
index 29514a5..55b187c 100644
--- a/src/compiler/glsl/ast_to_hir.cpp
+++ b/src/compiler/glsl/ast_to_hir.cpp
@@ -1254,6 +1254,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);
@@ -1973,6 +1977,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.
@@ -2099,6 +2111,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:
diff --git a/src/compiler/glsl/glsl_lexer.ll b/src/compiler/glsl/glsl_lexer.ll
index 9c6d943..7145b23 100644
--- a/src/compiler/glsl/glsl_lexer.ll
+++ b/src/compiler/glsl/glsl_lexer.ll
@@ -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) \
@@ -458,13 +473,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);
 			}
 
diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy
index 2cd4ed8..a630e4a 100644
--- a/src/compiler/glsl/glsl_parser.yy
+++ b/src/compiler/glsl/glsl_parser.yy
@@ -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
@@ -454,6 +456,20 @@ primary_expression:
       $$->set_location(@1);
       $$->primary_expression.uint_constant = $1;
    }
+   | INT64CONSTANT
+   {
+      void *ctx = state;
+      $$ = new(ctx) ast_expression(ast_int64_constant, NULL, NULL, NULL);
+      $$->set_location(@1);
+      $$->primary_expression.int64_constant = $1;
+   }
+   | UINT64CONSTANT
+   {
+      void *ctx = state;
+      $$ = new(ctx) ast_expression(ast_uint64_constant, NULL, NULL, NULL);
+      $$->set_location(@1);
+      $$->primary_expression.uint64_constant = $1;
+   }
    | FLOATCONSTANT
    {
       void *ctx = state;
diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp
index e2b58a9..31d2770 100644
--- a/src/compiler/glsl/glsl_parser_extras.cpp
+++ b/src/compiler/glsl/glsl_parser_extras.cpp
@@ -1195,6 +1195,14 @@ ast_expression::print(void) const
       printf("%f ", primary_expression.double_constant);
       break;
 
+   case ast_int64_constant:
+      printf("%ld ", primary_expression.int64_constant);
+      break;
+
+   case ast_uint64_constant:
+      printf("%lu ", primary_expression.uint64_constant);
+      break;
+
    case ast_bool_constant:
       printf("%s ",
 	     primary_expression.bool_constant
diff --git a/src/compiler/glsl/ir.cpp b/src/compiler/glsl/ir.cpp
index 7961f00..8b7572c 100644
--- a/src/compiler/glsl/ir.cpp
+++ b/src/compiler/glsl/ir.cpp
@@ -740,6 +740,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)
 {
@@ -905,6 +931,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.
 	     */
@@ -958,6 +990,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;
    }
 
@@ -976,6 +1010,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;
    }
 
@@ -994,6 +1030,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;
    }
 
@@ -1012,6 +1050,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;
    }
 
@@ -1030,6 +1070,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;
    }
 
@@ -1095,6 +1177,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);
@@ -1115,6 +1199,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;
 	 }
@@ -1174,6 +1264,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;
@@ -1238,6 +1334,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;
@@ -1279,6 +1383,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
diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h
index 3629356..5a325c2 100644
--- a/src/compiler/glsl/ir.h
+++ b/src/compiler/glsl/ir.h
@@ -2292,6 +2292,8 @@ union ir_constant_data {
       float f[16];
       bool b[16];
       double d[16];
+      uint64_t u64[16];
+      int64_t i64[16];
 };
 
 
@@ -2303,6 +2305,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
@@ -2353,6 +2357,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;
-- 
2.5.5



More information about the mesa-dev mailing list