Add support for 'k', 'M', and 'G' suffixes to integer constants.

(Denoting units of 1024, 1024*1024, and 1024*1024*1024, respectively.)

Issue #128.
This commit is contained in:
Matt Pharr
2012-01-06 14:47:47 -08:00
parent 11033e108e
commit 8da9be1a09
5 changed files with 83 additions and 20 deletions

View File

@@ -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

52
lex.ll
View File

@@ -42,7 +42,7 @@
#include <stdlib.h>
#include <stdint.h>
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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}