diff --git a/docs/ispc.txt b/docs/ispc.txt index 5d9ea2b0..32e5017c 100644 --- a/docs/ispc.txt +++ b/docs/ispc.txt @@ -1247,6 +1247,18 @@ Here are three ways of specifying the integer value "15": int fifteen_hex = 0xf; int fifteen_binary = 0b1111; +A number of suffixes can be provided with integer numeric constants. +First, "u" denotes that the constant is unsigned, and "ll" denotes a 64-bit +integer constant (while "l" denotes a 32-bit integer constant). It is also +possible to denote units of 1024, 1024*1024, or 1024*1024*1024 with the +SI-inspired suffixes "k", "M", and "G" respectively: + +:: + + int two_kb = 2k; // 2048 + int two_megs = 2M; // 2 * 1024 * 1024 + int one_gig = 1G; // 1024 * 1024 * 1024 + Floating-point constants can be specified in one of three ways. First, they may be a sequence of zero or more digits from 0 to 9, followed by a period, followed by zero or more digits from 0 to 9. (There must be at diff --git a/lex.ll b/lex.ll index f4161c94..39194767 100644 --- a/lex.ll +++ b/lex.ll @@ -42,7 +42,7 @@ #include #include -static uint64_t lParseBinary(const char *ptr, SourcePos pos); +static uint64_t lParseBinary(const char *ptr, SourcePos pos, char **endPtr); static void lCComment(SourcePos *); static void lCppComment(SourcePos *); static void lHandleCppHash(SourcePos *); @@ -67,7 +67,7 @@ inline int isatty(int) { return 0; } %option nounistd WHITESPACE [ \t\r]+ -INT_NUMBER (([0-9]+)|(0x[0-9a-fA-F]+)|(0b[01]+)) +INT_NUMBER (([0-9]+)|(0x[0-9a-fA-F]+)|(0b[01]+))[kMG]? FLOAT_NUMBER (([0-9]+|(([0-9]+\.[0-9]*[fF]?)|(\.[0-9]+)))([eE][-+]?[0-9]+)?[fF]?) HEX_FLOAT_NUMBER (0x[01](\.[0-9a-fA-F]*)?p[-+]?[0-9]+[fF]?) @@ -151,11 +151,10 @@ L?\"(\\.|[^\\"])*\" { lStringConst(yylval, yylloc); return TOKEN_STRING_LITERAL; {INT_NUMBER}+(u|U|l|L)*? { int ls = 0, us = 0; + char *endPtr = NULL; if (yytext[0] == '0' && yytext[1] == 'b') - yylval->intVal = lParseBinary(yytext+2, *yylloc); + yylval->intVal = lParseBinary(yytext+2, *yylloc, &endPtr); else { - char *endPtr = NULL; - #ifdef ISPC_IS_WINDOWS yylval->intVal = _strtoi64(yytext, &endPtr, 0); #else @@ -163,18 +162,33 @@ L?\"(\\.|[^\\"])*\" { lStringConst(yylval, yylloc); return TOKEN_STRING_LITERAL; // fit into 64 bits... yylval->intVal = strtoull(yytext, &endPtr, 0); #endif - for (; *endPtr; endPtr++) { - if (*endPtr == 'l' || *endPtr == 'L') - ls++; - else if (*endPtr == 'u' || *endPtr == 'U') - us++; - } - if (ls >= 2) - return us ? TOKEN_UINT64_CONSTANT : TOKEN_INT64_CONSTANT; - else if (ls == 1) - return us ? TOKEN_UINT32_CONSTANT : TOKEN_INT32_CONSTANT; } + bool kilo = false, mega = false, giga = false; + for (; *endPtr; endPtr++) { + if (*endPtr == 'k') + kilo = true; + else if (*endPtr == 'M') + mega = true; + else if (*endPtr == 'G') + giga = true; + else if (*endPtr == 'l' || *endPtr == 'L') + ls++; + else if (*endPtr == 'u' || *endPtr == 'U') + us++; + } + if (kilo) + yylval->intVal *= 1024; + if (mega) + yylval->intVal *= 1024*1024; + if (giga) + yylval->intVal *= 1024*1024*1024; + + if (ls >= 2) + return us ? TOKEN_UINT64_CONSTANT : TOKEN_INT64_CONSTANT; + else if (ls == 1) + return us ? TOKEN_UINT32_CONSTANT : TOKEN_INT32_CONSTANT; + // See if we can fit this into a 32-bit integer... if ((yylval->intVal & 0xffffffff) == yylval->intVal) return us ? TOKEN_UINT32_CONSTANT : TOKEN_INT32_CONSTANT; @@ -268,14 +282,11 @@ L?\"(\\.|[^\\"])*\" { lStringConst(yylval, yylloc); return TOKEN_STRING_LITERAL; /** Return the integer version of a binary constant from a string. */ static uint64_t -lParseBinary(const char *ptr, SourcePos pos) { +lParseBinary(const char *ptr, SourcePos pos, char **endPtr) { 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'); - + while (*ptr == '0' || *ptr == '1') { if ((val & (((int64_t)1)<<63)) && warned == false) { // We're about to shift out a set bit Warning(pos, "Can't represent binary constant with a 64-bit integer type"); @@ -285,6 +296,7 @@ lParseBinary(const char *ptr, SourcePos pos) { val = (val << 1) | (*ptr == '0' ? 0 : 1); ++ptr; } + *endPtr = (char *)ptr; return val; } diff --git a/tests/kilo-mega-giga-1.ispc b/tests/kilo-mega-giga-1.ispc new file mode 100644 index 00000000..9ae8f87e --- /dev/null +++ b/tests/kilo-mega-giga-1.ispc @@ -0,0 +1,13 @@ + +export uniform int width() { return programCount; } + + +export void f_f(uniform float RET[], uniform float aFOO[]) { + float a = aFOO[programIndex]; + a *= 1k; + RET[programIndex] = a; +} + +export void result(uniform float RET[]) { + RET[programIndex] = 1024*(programIndex+1); +} diff --git a/tests/kilo-mega-giga-2.ispc b/tests/kilo-mega-giga-2.ispc new file mode 100644 index 00000000..77e201ef --- /dev/null +++ b/tests/kilo-mega-giga-2.ispc @@ -0,0 +1,12 @@ + +export uniform int width() { return programCount; } + + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + int a = b + 2M; + RET[programIndex] = a; +} + +export void result(uniform float RET[]) { + RET[programIndex] = 2*1024*1024 + 5; +} diff --git a/tests/kilo-mega-giga-3.ispc b/tests/kilo-mega-giga-3.ispc new file mode 100644 index 00000000..aa80e8be --- /dev/null +++ b/tests/kilo-mega-giga-3.ispc @@ -0,0 +1,14 @@ + +export uniform int width() { return programCount; } + + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + unsigned int32 a = 3G; + a -= 2G; + a -= 1024M; + RET[programIndex] = a; +} + +export void result(uniform float RET[]) { + RET[programIndex] = 0; +}