diff --git a/lex.ll b/lex.ll index 91783512..f589b904 100644 --- a/lex.ll +++ b/lex.ll @@ -39,8 +39,9 @@ #include "sym.h" #include "util.h" #include "module.h" +#include -static uint32_t lParseBinary(const char *ptr, SourcePos pos); +static uint64_t lParseBinary(const char *ptr, SourcePos pos); static void lCComment(SourcePos *); static void lCppComment(SourcePos *); static void lHandleCppHash(SourcePos *); @@ -136,51 +137,54 @@ L?\"(\\.|[^\\"])*\" { lStringConst(yylval, yylloc); return TOKEN_STRING_LITERAL; {INT_NUMBER} { char *endPtr = NULL; -#ifdef ISPC_IS_WINDOWS - unsigned long val; -#else - unsigned long long val; -#endif + int64_t val; if (yytext[0] == '0' && yytext[1] == 'b') val = lParseBinary(yytext+2, *yylloc); else { #ifdef ISPC_IS_WINDOWS - val = strtoul(yytext, &endPtr, 0); + val = _strtoi64(yytext, &endPtr, 0); #else + // FIXME: should use strtouq and then issue an error if we can't + // fit into 64 bits... val = strtoull(yytext, &endPtr, 0); #endif } - yylval->int32Val = (int32_t)val; - if (val != (unsigned int)yylval->int32Val) - Warning(*yylloc, "32-bit integer has insufficient bits to represent value %s (%x %llx)", - yytext, yylval->int32Val, (unsigned long long)val); - return TOKEN_INT_CONSTANT; + + // See if we can fit this into a 32-bit integer... + if ((val & 0xffffffff) == val) { + yylval->int32Val = (int32_t)val; + return TOKEN_INT32_CONSTANT; + } + else { + yylval->int64Val = val; + return TOKEN_INT64_CONSTANT; + } } {INT_NUMBER}[uU] { char *endPtr = NULL; -#ifdef ISPC_IS_WINDOWS - unsigned long val; -#else - unsigned long long val; -#endif + uint64_t val; if (yytext[0] == '0' && yytext[1] == 'b') val = lParseBinary(yytext+2, *yylloc); else { #ifdef ISPC_IS_WINDOWS - val = strtoul(yytext, &endPtr, 0); + val = _strtoui64(yytext, &endPtr, 0); #else val = strtoull(yytext, &endPtr, 0); #endif } - yylval->int32Val = (int32_t)val; - if (val != (unsigned int)yylval->int32Val) - Warning(*yylloc, "32-bit integer has insufficient bits to represent value %s (%x %llx)", - yytext, yylval->int32Val, (unsigned long long)val); - return TOKEN_UINT_CONSTANT; + if ((val & 0xffffffff) == val) { + // we can represent it in a 32-bit value + yylval->int32Val = (int32_t)val; + return TOKEN_UINT32_CONSTANT; + } + else { + yylval->int64Val = val; + return TOKEN_UINT64_CONSTANT; + } } {FLOAT_NUMBER} { @@ -268,19 +272,18 @@ L?\"(\\.|[^\\"])*\" { lStringConst(yylval, yylloc); return TOKEN_STRING_LITERAL; /** Return the integer version of a binary constant from a string. */ -static uint32_t +static uint64_t lParseBinary(const char *ptr, SourcePos pos) { - uint32_t val = 0; + uint64_t val = 0; bool warned = false; while (*ptr != '\0') { /* if this hits, the regexp for 0b... constants is broken */ assert(*ptr == '0' || *ptr == '1'); - if ((val & (1<<31)) && warned == false) { + if ((val & (((int64_t)1)<<63)) && warned == false) { // We're about to shift out a set bit - // FIXME: 64-bit int constants... - Warning(pos, "Can't represent binary constant with 32-bit integer type"); + Warning(pos, "Can't represent binary constant with a 64-bit integer type"); warned = true; } diff --git a/parse.yy b/parse.yy index c23dca36..06761dba 100644 --- a/parse.yy +++ b/parse.yy @@ -129,17 +129,16 @@ static const char *lParamListTokens[] = { StructDeclaration *structDeclaration; std::vector *structDeclarationList; int32_t int32Val; - uint32_t uint32Val; double floatVal; int64_t int64Val; - uint64_t uint64Val; std::string *stringVal; const char *constCharPtr; } -%token TOKEN_IDENTIFIER TOKEN_INT_CONSTANT TOKEN_UINT_CONSTANT TOKEN_FLOAT_CONSTANT -%token TOKEN_STRING_LITERAL TOKEN_TYPE_NAME +%token TOKEN_INT32_CONSTANT TOKEN_UINT32_CONSTANT TOKEN_INT64_CONSTANT +%token TOKEN_UINT64_CONSTANT TOKEN_FLOAT_CONSTANT +%token TOKEN_IDENTIFIER TOKEN_STRING_LITERAL TOKEN_TYPE_NAME %token TOKEN_PTR_OP TOKEN_INC_OP TOKEN_DEC_OP TOKEN_LEFT_OP TOKEN_RIGHT_OP %token TOKEN_LE_OP TOKEN_GE_OP TOKEN_EQ_OP TOKEN_NE_OP %token TOKEN_AND_OP TOKEN_OR_OP TOKEN_MUL_ASSIGN TOKEN_DIV_ASSIGN TOKEN_MOD_ASSIGN @@ -220,12 +219,17 @@ primary_expression Error(@1, "Undeclared symbol \"%s\".%s", name, alts.c_str()); } } - | TOKEN_INT_CONSTANT { - /* FIXME: should support 64 bit constants (and doubles...) */ + | TOKEN_INT32_CONSTANT { $$ = new ConstExpr(AtomicType::UniformConstInt32, yylval.int32Val, @1); } - | TOKEN_UINT_CONSTANT { - $$ = new ConstExpr(AtomicType::UniformConstUInt32, yylval.uint32Val, @1); + | TOKEN_UINT32_CONSTANT { + $$ = new ConstExpr(AtomicType::UniformConstUInt32, (uint32_t)yylval.int32Val, @1); + } + | TOKEN_INT64_CONSTANT { + $$ = new ConstExpr(AtomicType::UniformConstInt64, yylval.int64Val, @1); + } + | TOKEN_UINT64_CONSTANT { + $$ = new ConstExpr(AtomicType::UniformConstUInt64, (uint64_t)yylval.int64Val, @1); } | TOKEN_FLOAT_CONSTANT { $$ = new ConstExpr(AtomicType::UniformConstFloat, (float)yylval.floatVal, @1); @@ -740,7 +744,7 @@ declarator ; int_constant - : TOKEN_INT_CONSTANT { $$ = yylval.int32Val; } + : TOKEN_INT32_CONSTANT { $$ = yylval.int32Val; } ; direct_declarator