[Mesa-dev] [PATCH] glsl: Implement GLSL 1.30's literal integer range restrictions.
Kenneth Graunke
kenneth at whitecape.org
Mon Oct 3 17:19:44 PDT 2011
On 10/03/2011 05:03 PM, Eric Anholt wrote:
> From page 22 (28 of PDF) of GLSL 1.30 spec:
> It is an error to provide a literal integer whose magnitude is too
> large to store in a variable of matching signed or unsigned type.
>
> Unsigned integers have exactly 32 bits of precision. Signed integers
> use 32 bits, including a sign bit, in two's complement form.
> ---
>
> Others read this as "0xffffffff" being a valid literal integer of -1,
> like in C, right?
I would assume so. I suppose I could check other implementations, but
I'm not sure I care enough to bother. It's completely reasonable.
> src/glsl/glsl_lexer.ll | 38 ++++++++++++++++++++++++++++++--------
> 1 files changed, 30 insertions(+), 8 deletions(-)
>
> diff --git a/src/glsl/glsl_lexer.ll b/src/glsl/glsl_lexer.ll
> index cfd8926..b01dcde 100644
> --- a/src/glsl/glsl_lexer.ll
> +++ b/src/glsl/glsl_lexer.ll
> @@ -22,6 +22,7 @@
> * DEALINGS IN THE SOFTWARE.
> */
> #include <ctype.h>
> +#include <limits.h>
> #include "strtod.h"
> #include "ast.h"
> #include "glsl_parser_extras.h"
> @@ -43,8 +44,6 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
>
> #define YY_USER_INIT yylineno = 0; yycolumn = 0;
>
> -#define IS_UINT (yytext[yyleng - 1] == 'u' || yytext[yyleng - 1] == 'U')
> -
> /* A macro for handling reserved words and keywords across language versions.
> *
> * Certain words start out as identifiers, become reserved words in
> @@ -81,6 +80,32 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
> * ...means the word is a legal keyword in GLSL ES 1.00.
> */
> #define ES yyextra->es_shader
> +
> +#define LITERAL_INTEGER(base) \
> +do { \
I might just use a function for this...
> + bool is_uint = (yytext[yyleng - 1] == 'u' || \
> + yytext[yyleng - 1] == 'U'); \
> + const char *digits = yytext; \
> + \
> + if (base == 16) \
> + digits += 2; \
> + long long value = strtoll(digits, NULL, base); \
> + \
> + yylval->n = (int)value; \
> + \
> + if (value > UINT_MAX) { \
Won't this give a signed/unsigned comparison warning? I think this is
the right thing to do though.
> + /* Note that signed 0xffffffff is valid, not out of range! */ \
> + if (yyextra->language_version >= 130) { \
> + _mesa_glsl_error(yylloc, yyextra, \
> + "Literal value `%s' out of range", yytext); \
> + } else { \
> + _mesa_glsl_warning(yylloc, yyextra, \
> + "Literal value `%s' out of range", yytext); \
> + } \
> + } \
> + return is_uint ? UINTCONSTANT : INTCONSTANT; \
> +} while (0)
> +
> %}
>
> %option bison-bridge bison-locations reentrant noyywrap
> @@ -292,16 +317,13 @@ layout {
> -= return SUB_ASSIGN;
>
> [1-9][0-9]*[uU]? {
> - yylval->n = strtol(yytext, NULL, 10);
> - return IS_UINT ? UINTCONSTANT : INTCONSTANT;
> + LITERAL_INTEGER(10);
> }
> 0[xX][0-9a-fA-F]+[uU]? {
> - yylval->n = strtol(yytext + 2, NULL, 16);
> - return IS_UINT ? UINTCONSTANT : INTCONSTANT;
> + LITERAL_INTEGER(16);
> }
> 0[0-7]*[uU]? {
> - yylval->n = strtol(yytext, NULL, 8);
> - return IS_UINT ? UINTCONSTANT : INTCONSTANT;
> + LITERAL_INTEGER(8);
> }
>
> [0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fF]? {
More information about the mesa-dev
mailing list