Add fuzz testing of input programs.
When the --fuzz-test command-line option is given, the input program will be randomly perturbed by the lexer in an effort to trigger assertions or crashes in the compiler (neither of which should ever happen, even for malformed programs.)
This commit is contained in:
4
ispc.cpp
4
ispc.cpp
@@ -515,8 +515,10 @@ Globals::Globals() {
|
||||
emitPerfWarnings = true;
|
||||
emitInstrumentation = false;
|
||||
generateDebuggingSymbols = false;
|
||||
enableFuzzTest = false;
|
||||
fuzzTestSeed = -1;
|
||||
mangleFunctionsWithTarget = false;
|
||||
|
||||
|
||||
ctx = new llvm::LLVMContext;
|
||||
|
||||
#ifdef ISPC_IS_WINDOWS
|
||||
|
||||
8
ispc.h
8
ispc.h
@@ -405,6 +405,14 @@ struct Globals {
|
||||
vector width to them. */
|
||||
bool mangleFunctionsWithTarget;
|
||||
|
||||
/** If enabled, the lexer will randomly replace some tokens returned
|
||||
with other tokens, in order to test error condition handling in the
|
||||
compiler. */
|
||||
bool enableFuzzTest;
|
||||
|
||||
/** Seed for random number generator used for fuzz testing. */
|
||||
int fuzzTestSeed;
|
||||
|
||||
/** Global LLVMContext object */
|
||||
llvm::LLVMContext *ctx;
|
||||
|
||||
|
||||
382
lex.ll
382
lex.ll
@@ -58,6 +58,178 @@ static double lParseHexFloat(const char *ptr);
|
||||
inline int isatty(int) { return 0; }
|
||||
#endif // ISPC_IS_WINDOWS
|
||||
|
||||
static int allTokens[] = {
|
||||
TOKEN_ASSERT, TOKEN_BOOL, TOKEN_BREAK, TOKEN_CASE, TOKEN_CBREAK,
|
||||
TOKEN_CCONTINUE, TOKEN_CDO, TOKEN_CFOR, TOKEN_CIF, TOKEN_CWHILE,
|
||||
TOKEN_CONST, TOKEN_CONTINUE, TOKEN_CRETURN, TOKEN_DEFAULT, TOKEN_DO,
|
||||
TOKEN_DELETE, TOKEN_DELETE, TOKEN_DOUBLE, TOKEN_ELSE, TOKEN_ENUM,
|
||||
TOKEN_EXPORT, TOKEN_EXTERN, TOKEN_FALSE, TOKEN_FLOAT, TOKEN_FOR,
|
||||
TOKEN_FOREACH, TOKEN_FOREACH_TILED, TOKEN_GOTO, TOKEN_IF, TOKEN_INLINE,
|
||||
TOKEN_INT, TOKEN_INT8, TOKEN_INT16, TOKEN_INT, TOKEN_INT64, TOKEN_LAUNCH,
|
||||
TOKEN_NEW, TOKEN_NULL, TOKEN_PRINT, TOKEN_RETURN, TOKEN_SOA, TOKEN_SIGNED,
|
||||
TOKEN_SIZEOF, TOKEN_STATIC, TOKEN_STRUCT, TOKEN_SWITCH, TOKEN_SYNC,
|
||||
TOKEN_TASK, TOKEN_TRUE, TOKEN_TYPEDEF, TOKEN_UNIFORM, TOKEN_UNSIGNED,
|
||||
TOKEN_VARYING, TOKEN_VOID, TOKEN_WHILE, TOKEN_STRING_C_LITERAL,
|
||||
TOKEN_DOTDOTDOT,
|
||||
TOKEN_FLOAT_CONSTANT,
|
||||
TOKEN_INT32_CONSTANT, TOKEN_UINT32_CONSTANT,
|
||||
TOKEN_INT64_CONSTANT, TOKEN_UINT64_CONSTANT,
|
||||
TOKEN_INC_OP, TOKEN_DEC_OP, TOKEN_LEFT_OP, TOKEN_RIGHT_OP, TOKEN_LE_OP,
|
||||
TOKEN_GE_OP, TOKEN_EQ_OP, TOKEN_NE_OP, TOKEN_AND_OP, TOKEN_OR_OP,
|
||||
TOKEN_MUL_ASSIGN, TOKEN_DIV_ASSIGN, TOKEN_MOD_ASSIGN, TOKEN_ADD_ASSIGN,
|
||||
TOKEN_SUB_ASSIGN, TOKEN_LEFT_ASSIGN, TOKEN_RIGHT_ASSIGN, TOKEN_AND_ASSIGN,
|
||||
TOKEN_XOR_ASSIGN, TOKEN_OR_ASSIGN, TOKEN_PTR_OP,
|
||||
';', '{', '}', ',', ':', '=', '(', ')', '[', ']', '.', '&', '!', '~', '-',
|
||||
'+', '*', '/', '%', '<', '>', '^', '|', '?',
|
||||
};
|
||||
|
||||
static std::map<int, std::string> tokenToName;
|
||||
|
||||
static void lInitTokenToName() {
|
||||
tokenToName[TOKEN_ASSERT] = "assert";
|
||||
tokenToName[TOKEN_BOOL] = "bool";
|
||||
tokenToName[TOKEN_BREAK] = "break";
|
||||
tokenToName[TOKEN_CASE] = "case";
|
||||
tokenToName[TOKEN_CBREAK] = "cbreak";
|
||||
tokenToName[TOKEN_CCONTINUE] = "ccontinue";
|
||||
tokenToName[TOKEN_CDO] = "cdo";
|
||||
tokenToName[TOKEN_CFOR] = "cfor";
|
||||
tokenToName[TOKEN_CIF] = "cif";
|
||||
tokenToName[TOKEN_CWHILE] = "cwhile";
|
||||
tokenToName[TOKEN_CONST] = "const";
|
||||
tokenToName[TOKEN_CONTINUE] = "continue";
|
||||
tokenToName[TOKEN_CRETURN] = "creturn";
|
||||
tokenToName[TOKEN_DEFAULT] = "default";
|
||||
tokenToName[TOKEN_DO] = "do";
|
||||
tokenToName[TOKEN_DELETE] = "delete";
|
||||
tokenToName[TOKEN_DELETE] = "delete";
|
||||
tokenToName[TOKEN_DOUBLE] = "double";
|
||||
tokenToName[TOKEN_ELSE] = "else";
|
||||
tokenToName[TOKEN_ENUM] = "enum";
|
||||
tokenToName[TOKEN_EXPORT] = "export";
|
||||
tokenToName[TOKEN_EXTERN] = "extern";
|
||||
tokenToName[TOKEN_FALSE] = "false";
|
||||
tokenToName[TOKEN_FLOAT] = "float";
|
||||
tokenToName[TOKEN_FOR] = "for";
|
||||
tokenToName[TOKEN_FOREACH] = "foreach";
|
||||
tokenToName[TOKEN_FOREACH_TILED] = "foreach_tiled";
|
||||
tokenToName[TOKEN_GOTO] = "goto";
|
||||
tokenToName[TOKEN_IF] = "if";
|
||||
tokenToName[TOKEN_INLINE] = "inline";
|
||||
tokenToName[TOKEN_INT] = "int";
|
||||
tokenToName[TOKEN_INT8] = "int8";
|
||||
tokenToName[TOKEN_INT16] = "int16";
|
||||
tokenToName[TOKEN_INT] = "int";
|
||||
tokenToName[TOKEN_INT64] = "int64";
|
||||
tokenToName[TOKEN_LAUNCH] = "launch";
|
||||
tokenToName[TOKEN_NEW] = "new";
|
||||
tokenToName[TOKEN_NULL] = "NULL";
|
||||
tokenToName[TOKEN_PRINT] = "print";
|
||||
tokenToName[TOKEN_RETURN] = "return";
|
||||
tokenToName[TOKEN_SOA] = "soa";
|
||||
tokenToName[TOKEN_SIGNED] = "signed";
|
||||
tokenToName[TOKEN_SIZEOF] = "sizeof";
|
||||
tokenToName[TOKEN_STATIC] = "static";
|
||||
tokenToName[TOKEN_STRUCT] = "struct";
|
||||
tokenToName[TOKEN_SWITCH] = "switch";
|
||||
tokenToName[TOKEN_SYNC] = "sync";
|
||||
tokenToName[TOKEN_TASK] = "task";
|
||||
tokenToName[TOKEN_TRUE] = "true";
|
||||
tokenToName[TOKEN_TYPEDEF] = "typedef";
|
||||
tokenToName[TOKEN_UNIFORM] = "uniform";
|
||||
tokenToName[TOKEN_UNSIGNED] = "unsigned";
|
||||
tokenToName[TOKEN_VARYING] = "varying";
|
||||
tokenToName[TOKEN_VOID] = "void";
|
||||
tokenToName[TOKEN_WHILE] = "while";
|
||||
tokenToName[TOKEN_STRING_C_LITERAL] = "\"C\"";
|
||||
tokenToName[TOKEN_DOTDOTDOT] = "...";
|
||||
tokenToName[TOKEN_FLOAT_CONSTANT] = "TOKEN_FLOAT_CONSTANT";
|
||||
tokenToName[TOKEN_INT32_CONSTANT] = "TOKEN_INT32_CONSTANT";
|
||||
tokenToName[TOKEN_UINT32_CONSTANT] = "TOKEN_UINT32_CONSTANT";
|
||||
tokenToName[TOKEN_INT64_CONSTANT] = "TOKEN_INT64_CONSTANT";
|
||||
tokenToName[TOKEN_UINT64_CONSTANT] = "TOKEN_UINT64_CONSTANT";
|
||||
tokenToName[TOKEN_INC_OP] = "++";
|
||||
tokenToName[TOKEN_DEC_OP] = "--";
|
||||
tokenToName[TOKEN_LEFT_OP] = "<<";
|
||||
tokenToName[TOKEN_RIGHT_OP] = ">>";
|
||||
tokenToName[TOKEN_LE_OP] = "<=";
|
||||
tokenToName[TOKEN_GE_OP] = ">=";
|
||||
tokenToName[TOKEN_EQ_OP] = "==";
|
||||
tokenToName[TOKEN_NE_OP] = "!=";
|
||||
tokenToName[TOKEN_AND_OP] = "&&";
|
||||
tokenToName[TOKEN_OR_OP] = "||";
|
||||
tokenToName[TOKEN_MUL_ASSIGN] = "*=";
|
||||
tokenToName[TOKEN_DIV_ASSIGN] = "/=";
|
||||
tokenToName[TOKEN_MOD_ASSIGN] = "%=";
|
||||
tokenToName[TOKEN_ADD_ASSIGN] = "+=";
|
||||
tokenToName[TOKEN_SUB_ASSIGN] = "-=";
|
||||
tokenToName[TOKEN_LEFT_ASSIGN] = "<<=";
|
||||
tokenToName[TOKEN_RIGHT_ASSIGN] = ">>=";
|
||||
tokenToName[TOKEN_AND_ASSIGN] = "&=";
|
||||
tokenToName[TOKEN_XOR_ASSIGN] = "^=";
|
||||
tokenToName[TOKEN_OR_ASSIGN] = "|=";
|
||||
tokenToName[TOKEN_PTR_OP] = "->";
|
||||
tokenToName[';'] = ";";
|
||||
tokenToName['{'] = "{";
|
||||
tokenToName['}'] = "}";
|
||||
tokenToName[','] = ",";
|
||||
tokenToName[':'] = ":";
|
||||
tokenToName['='] = "=";
|
||||
tokenToName['('] = "(";
|
||||
tokenToName[')'] = ")";
|
||||
tokenToName['['] = "[";
|
||||
tokenToName[']'] = "]";
|
||||
tokenToName['.'] = ".";
|
||||
tokenToName['&'] = "&";
|
||||
tokenToName['!'] = "!";
|
||||
tokenToName['~'] = "~";
|
||||
tokenToName['-'] = "-";
|
||||
tokenToName['+'] = "+";
|
||||
tokenToName['*'] = "*";
|
||||
tokenToName['/'] = "/";
|
||||
tokenToName['%'] = "%";
|
||||
tokenToName['<'] = "<";
|
||||
tokenToName['>'] = ">";
|
||||
tokenToName['^'] = "^";
|
||||
tokenToName['|'] = "|";
|
||||
tokenToName['?'] = "?";
|
||||
tokenToName[';'] = ";";
|
||||
}
|
||||
|
||||
|
||||
inline int ispcRand() {
|
||||
#ifdef ISPC_IS_WINDOWS
|
||||
return rand();
|
||||
#else
|
||||
return lrand48();
|
||||
#endif
|
||||
}
|
||||
|
||||
#define RT \
|
||||
if (g->enableFuzzTest) { \
|
||||
int r = ispcRand() % 40; \
|
||||
if (r == 0) { \
|
||||
Warning(*yylloc, "Dropping token"); \
|
||||
} \
|
||||
else if (r == 1) { \
|
||||
if (tokenToName.size() == 0) lInitTokenToName(); \
|
||||
int nt = sizeof(allTokens) / sizeof(allTokens[0]); \
|
||||
int tn = ispcRand() % nt; \
|
||||
yylval->stringVal = new std::string(yytext); /* just in case */\
|
||||
Warning(*yylloc, "Replaced with \"%s\"", tokenToName[allTokens[tn]].c_str()); \
|
||||
return allTokens[tn]; \
|
||||
} \
|
||||
else if (r == 2) { \
|
||||
Symbol *sym = m->symbolTable->RandomSymbol(); \
|
||||
if (sym != NULL) { \
|
||||
yylval->stringVal = new std::string(sym->name); \
|
||||
Warning(*yylloc, "Replaced with identifier \"%s\".", sym->name.c_str()); \
|
||||
return TOKEN_IDENTIFIER; \
|
||||
} \
|
||||
} \
|
||||
/* TOKEN_TYPE_NAME */ \
|
||||
} else /* swallow semicolon */
|
||||
|
||||
%}
|
||||
|
||||
%option nounput
|
||||
@@ -78,70 +250,71 @@ ZO_SWIZZLE ([01]+[w-z]+)+|([01]+[rgba]+)+|([01]+[uv]+)+
|
||||
"/*" { lCComment(yylloc); }
|
||||
"//" { lCppComment(yylloc); }
|
||||
|
||||
__assert { return TOKEN_ASSERT; }
|
||||
bool { return TOKEN_BOOL; }
|
||||
break { return TOKEN_BREAK; }
|
||||
case { return TOKEN_CASE; }
|
||||
cbreak { return TOKEN_CBREAK; }
|
||||
ccontinue { return TOKEN_CCONTINUE; }
|
||||
cdo { return TOKEN_CDO; }
|
||||
cfor { return TOKEN_CFOR; }
|
||||
cif { return TOKEN_CIF; }
|
||||
cwhile { return TOKEN_CWHILE; }
|
||||
const { return TOKEN_CONST; }
|
||||
continue { return TOKEN_CONTINUE; }
|
||||
creturn { return TOKEN_CRETURN; }
|
||||
default { return TOKEN_DEFAULT; }
|
||||
do { return TOKEN_DO; }
|
||||
delete { return TOKEN_DELETE; }
|
||||
delete\[\] { return TOKEN_DELETE; }
|
||||
double { return TOKEN_DOUBLE; }
|
||||
else { return TOKEN_ELSE; }
|
||||
enum { return TOKEN_ENUM; }
|
||||
export { return TOKEN_EXPORT; }
|
||||
extern { return TOKEN_EXTERN; }
|
||||
false { return TOKEN_FALSE; }
|
||||
float { return TOKEN_FLOAT; }
|
||||
for { return TOKEN_FOR; }
|
||||
foreach { return TOKEN_FOREACH; }
|
||||
foreach_tiled { return TOKEN_FOREACH_TILED; }
|
||||
goto { return TOKEN_GOTO; }
|
||||
if { return TOKEN_IF; }
|
||||
inline { return TOKEN_INLINE; }
|
||||
int { return TOKEN_INT; }
|
||||
int8 { return TOKEN_INT8; }
|
||||
int16 { return TOKEN_INT16; }
|
||||
int32 { return TOKEN_INT; }
|
||||
int64 { return TOKEN_INT64; }
|
||||
launch { return TOKEN_LAUNCH; }
|
||||
new { return TOKEN_NEW; }
|
||||
NULL { return TOKEN_NULL; }
|
||||
print { return TOKEN_PRINT; }
|
||||
__assert { RT; return TOKEN_ASSERT; }
|
||||
bool { RT; return TOKEN_BOOL; }
|
||||
break { RT; return TOKEN_BREAK; }
|
||||
case { RT; return TOKEN_CASE; }
|
||||
cbreak { RT; return TOKEN_CBREAK; }
|
||||
ccontinue { RT; return TOKEN_CCONTINUE; }
|
||||
cdo { RT; return TOKEN_CDO; }
|
||||
cfor { RT; return TOKEN_CFOR; }
|
||||
cif { RT; return TOKEN_CIF; }
|
||||
cwhile { RT; return TOKEN_CWHILE; }
|
||||
const { RT; return TOKEN_CONST; }
|
||||
continue { RT; return TOKEN_CONTINUE; }
|
||||
creturn { RT; return TOKEN_CRETURN; }
|
||||
default { RT; return TOKEN_DEFAULT; }
|
||||
do { RT; return TOKEN_DO; }
|
||||
delete { RT; return TOKEN_DELETE; }
|
||||
delete\[\] { RT; return TOKEN_DELETE; }
|
||||
double { RT; return TOKEN_DOUBLE; }
|
||||
else { RT; return TOKEN_ELSE; }
|
||||
enum { RT; return TOKEN_ENUM; }
|
||||
export { RT; return TOKEN_EXPORT; }
|
||||
extern { RT; return TOKEN_EXTERN; }
|
||||
false { RT; return TOKEN_FALSE; }
|
||||
float { RT; return TOKEN_FLOAT; }
|
||||
for { RT; return TOKEN_FOR; }
|
||||
foreach { RT; return TOKEN_FOREACH; }
|
||||
foreach_tiled { RT; return TOKEN_FOREACH_TILED; }
|
||||
goto { RT; return TOKEN_GOTO; }
|
||||
if { RT; return TOKEN_IF; }
|
||||
inline { RT; return TOKEN_INLINE; }
|
||||
int { RT; return TOKEN_INT; }
|
||||
int8 { RT; return TOKEN_INT8; }
|
||||
int16 { RT; return TOKEN_INT16; }
|
||||
int32 { RT; return TOKEN_INT; }
|
||||
int64 { RT; return TOKEN_INT64; }
|
||||
launch { RT; return TOKEN_LAUNCH; }
|
||||
new { RT; return TOKEN_NEW; }
|
||||
NULL { RT; return TOKEN_NULL; }
|
||||
print { RT; return TOKEN_PRINT; }
|
||||
reference { Error(*yylloc, "\"reference\" qualifier is no longer supported; "
|
||||
"please use C++-style '&' syntax for references "
|
||||
"instead."); }
|
||||
return { return TOKEN_RETURN; }
|
||||
soa { return TOKEN_SOA; }
|
||||
signed { return TOKEN_SIGNED; }
|
||||
sizeof { return TOKEN_SIZEOF; }
|
||||
static { return TOKEN_STATIC; }
|
||||
struct { return TOKEN_STRUCT; }
|
||||
switch { return TOKEN_SWITCH; }
|
||||
sync { return TOKEN_SYNC; }
|
||||
task { return TOKEN_TASK; }
|
||||
true { return TOKEN_TRUE; }
|
||||
typedef { return TOKEN_TYPEDEF; }
|
||||
uniform { return TOKEN_UNIFORM; }
|
||||
unsigned { return TOKEN_UNSIGNED; }
|
||||
varying { return TOKEN_VARYING; }
|
||||
void { return TOKEN_VOID; }
|
||||
while { return TOKEN_WHILE; }
|
||||
\"C\" { return TOKEN_STRING_C_LITERAL; }
|
||||
\.\.\. { return TOKEN_DOTDOTDOT; }
|
||||
return { RT; return TOKEN_RETURN; }
|
||||
soa { RT; return TOKEN_SOA; }
|
||||
signed { RT; return TOKEN_SIGNED; }
|
||||
sizeof { RT; return TOKEN_SIZEOF; }
|
||||
static { RT; return TOKEN_STATIC; }
|
||||
struct { RT; return TOKEN_STRUCT; }
|
||||
switch { RT; return TOKEN_SWITCH; }
|
||||
sync { RT; return TOKEN_SYNC; }
|
||||
task { RT; return TOKEN_TASK; }
|
||||
true { RT; return TOKEN_TRUE; }
|
||||
typedef { RT; return TOKEN_TYPEDEF; }
|
||||
uniform { RT; return TOKEN_UNIFORM; }
|
||||
unsigned { RT; return TOKEN_UNSIGNED; }
|
||||
varying { RT; return TOKEN_VARYING; }
|
||||
void { RT; return TOKEN_VOID; }
|
||||
while { RT; return TOKEN_WHILE; }
|
||||
\"C\" { RT; return TOKEN_STRING_C_LITERAL; }
|
||||
\.\.\. { RT; return TOKEN_DOTDOTDOT; }
|
||||
|
||||
L?\"(\\.|[^\\"])*\" { lStringConst(yylval, yylloc); return TOKEN_STRING_LITERAL; }
|
||||
|
||||
{IDENT} {
|
||||
RT;
|
||||
/* We have an identifier--is it a type name or an identifier?
|
||||
The symbol table will straighten us out... */
|
||||
yylval->stringVal = new std::string(yytext);
|
||||
@@ -152,6 +325,7 @@ L?\"(\\.|[^\\"])*\" { lStringConst(yylval, yylloc); return TOKEN_STRING_LITERAL;
|
||||
}
|
||||
|
||||
{INT_NUMBER}+(u|U|l|L)*? {
|
||||
RT;
|
||||
int ls = 0, us = 0;
|
||||
|
||||
char *endPtr = NULL;
|
||||
@@ -201,60 +375,62 @@ L?\"(\\.|[^\\"])*\" { lStringConst(yylval, yylloc); return TOKEN_STRING_LITERAL;
|
||||
|
||||
|
||||
{FLOAT_NUMBER} {
|
||||
yylval->floatVal = (float)atof(yytext);
|
||||
RT;
|
||||
yylval->floatVal = (float)atof(yytext);
|
||||
return TOKEN_FLOAT_CONSTANT;
|
||||
}
|
||||
|
||||
{HEX_FLOAT_NUMBER} {
|
||||
RT;
|
||||
yylval->floatVal = (float)lParseHexFloat(yytext);
|
||||
return TOKEN_FLOAT_CONSTANT;
|
||||
}
|
||||
|
||||
"++" { return TOKEN_INC_OP; }
|
||||
"--" { return TOKEN_DEC_OP; }
|
||||
"<<" { return TOKEN_LEFT_OP; }
|
||||
">>" { return TOKEN_RIGHT_OP; }
|
||||
"<=" { return TOKEN_LE_OP; }
|
||||
">=" { return TOKEN_GE_OP; }
|
||||
"==" { return TOKEN_EQ_OP; }
|
||||
"!=" { return TOKEN_NE_OP; }
|
||||
"&&" { return TOKEN_AND_OP; }
|
||||
"||" { return TOKEN_OR_OP; }
|
||||
"*=" { return TOKEN_MUL_ASSIGN; }
|
||||
"/=" { return TOKEN_DIV_ASSIGN; }
|
||||
"%=" { return TOKEN_MOD_ASSIGN; }
|
||||
"+=" { return TOKEN_ADD_ASSIGN; }
|
||||
"-=" { return TOKEN_SUB_ASSIGN; }
|
||||
"<<=" { return TOKEN_LEFT_ASSIGN; }
|
||||
">>=" { return TOKEN_RIGHT_ASSIGN; }
|
||||
"&=" { return TOKEN_AND_ASSIGN; }
|
||||
"^=" { return TOKEN_XOR_ASSIGN; }
|
||||
"|=" { return TOKEN_OR_ASSIGN; }
|
||||
"->" { return TOKEN_PTR_OP; }
|
||||
";" { return ';'; }
|
||||
("{"|"<%") { return '{'; }
|
||||
("}"|"%>") { return '}'; }
|
||||
"," { return ','; }
|
||||
":" { return ':'; }
|
||||
"=" { return '='; }
|
||||
"(" { return '('; }
|
||||
")" { return ')'; }
|
||||
("["|"<:") { return '['; }
|
||||
("]"|":>") { return ']'; }
|
||||
"." { return '.'; }
|
||||
"&" { return '&'; }
|
||||
"!" { return '!'; }
|
||||
"~" { return '~'; }
|
||||
"-" { return '-'; }
|
||||
"+" { return '+'; }
|
||||
"*" { return '*'; }
|
||||
"/" { return '/'; }
|
||||
"%" { return '%'; }
|
||||
"<" { return '<'; }
|
||||
">" { return '>'; }
|
||||
"^" { return '^'; }
|
||||
"|" { return '|'; }
|
||||
"?" { return '?'; }
|
||||
"++" { RT; return TOKEN_INC_OP; }
|
||||
"--" { RT; return TOKEN_DEC_OP; }
|
||||
"<<" { RT; return TOKEN_LEFT_OP; }
|
||||
">>" { RT; return TOKEN_RIGHT_OP; }
|
||||
"<=" { RT; return TOKEN_LE_OP; }
|
||||
">=" { RT; return TOKEN_GE_OP; }
|
||||
"==" { RT; return TOKEN_EQ_OP; }
|
||||
"!=" { RT; return TOKEN_NE_OP; }
|
||||
"&&" { RT; return TOKEN_AND_OP; }
|
||||
"||" { RT; return TOKEN_OR_OP; }
|
||||
"*=" { RT; return TOKEN_MUL_ASSIGN; }
|
||||
"/=" { RT; return TOKEN_DIV_ASSIGN; }
|
||||
"%=" { RT; return TOKEN_MOD_ASSIGN; }
|
||||
"+=" { RT; return TOKEN_ADD_ASSIGN; }
|
||||
"-=" { RT; return TOKEN_SUB_ASSIGN; }
|
||||
"<<=" { RT; return TOKEN_LEFT_ASSIGN; }
|
||||
">>=" { RT; return TOKEN_RIGHT_ASSIGN; }
|
||||
"&=" { RT; return TOKEN_AND_ASSIGN; }
|
||||
"^=" { RT; return TOKEN_XOR_ASSIGN; }
|
||||
"|=" { RT; return TOKEN_OR_ASSIGN; }
|
||||
"->" { RT; return TOKEN_PTR_OP; }
|
||||
";" { RT; return ';'; }
|
||||
("{"|"<%") { RT; return '{'; }
|
||||
("}"|"%>") { RT; return '}'; }
|
||||
"," { RT; return ','; }
|
||||
":" { RT; return ':'; }
|
||||
"=" { RT; return '='; }
|
||||
"(" { RT; return '('; }
|
||||
")" { RT; return ')'; }
|
||||
("["|"<:") { RT; return '['; }
|
||||
("]"|":>") { RT; return ']'; }
|
||||
"." { RT; return '.'; }
|
||||
"&" { RT; return '&'; }
|
||||
"!" { RT; return '!'; }
|
||||
"~" { RT; return '~'; }
|
||||
"-" { RT; return '-'; }
|
||||
"+" { RT; return '+'; }
|
||||
"*" { RT; return '*'; }
|
||||
"/" { RT; return '/'; }
|
||||
"%" { RT; return '%'; }
|
||||
"<" { RT; return '<'; }
|
||||
">" { RT; return '>'; }
|
||||
"^" { RT; return '^'; }
|
||||
"|" { RT; return '|'; }
|
||||
"?" { RT; return '?'; }
|
||||
|
||||
{WHITESPACE} { }
|
||||
|
||||
|
||||
31
main.cpp
31
main.cpp
@@ -41,6 +41,9 @@
|
||||
#include "type.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef ISPC_IS_WINDOWS
|
||||
#include <time.h>
|
||||
#endif // ISPC_IS_WINDOWS
|
||||
#include <llvm/Support/PrettyStackTrace.h>
|
||||
#include <llvm/Support/Signals.h>
|
||||
#if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn)
|
||||
@@ -97,6 +100,10 @@ usage(int ret) {
|
||||
#endif // !LLVM_2_9
|
||||
printf(" [--emit-llvm]\t\t\tEmit LLVM bitode file as output\n");
|
||||
printf(" [--emit-obj]\t\t\tGenerate object file file as output (default)\n");
|
||||
#if 0
|
||||
printf(" [--fuzz-test]\t\t\tRandomly perturb program input to test error conditions\n");
|
||||
printf(" [--fuzz-seed=<value>]\t\tSeed value for RNG for fuzz testing\n");
|
||||
#endif
|
||||
printf(" [-g]\t\t\t\tGenerate debugging information\n");
|
||||
printf(" [--help]\t\t\t\tPrint help\n");
|
||||
printf(" [-h <name>/--header-outfile=<name>]\tOutput filename for header\n");
|
||||
@@ -144,7 +151,7 @@ usage(int ret) {
|
||||
/** We take arguments from both the command line as well as from the
|
||||
ISPC_ARGS environment variable. This function returns a new set of
|
||||
arguments representing the ones from those two sources merged together.
|
||||
*/
|
||||
*/
|
||||
static void lGetAllArgs(int Argc, char *Argv[], int &argc, char *argv[128]) {
|
||||
// Copy over the command line arguments (passed in)
|
||||
for (int i = 0; i < Argc; ++i)
|
||||
@@ -272,6 +279,10 @@ int main(int Argc, char *Argv[]) {
|
||||
ot = Module::Bitcode;
|
||||
else if (!strcmp(argv[i], "--emit-obj"))
|
||||
ot = Module::Object;
|
||||
else if (!strcmp(argv[i], "--fuzz-test"))
|
||||
g->enableFuzzTest = true;
|
||||
else if (!strncmp(argv[i], "--fuzz-seed=", 12))
|
||||
g->fuzzTestSeed = atoi(argv[i] + 12);
|
||||
else if (!strcmp(argv[i], "--target")) {
|
||||
// FIXME: should remove this way of specifying the target...
|
||||
if (++i == argc) {
|
||||
@@ -411,6 +422,24 @@ int main(int Argc, char *Argv[]) {
|
||||
if (debugSet && !optSet)
|
||||
g->opt.level = 0;
|
||||
|
||||
if (g->enableFuzzTest) {
|
||||
if (g->fuzzTestSeed == -1) {
|
||||
#ifdef ISPC_IS_WINDOWS
|
||||
int seed = (unsigned)time(NULL);
|
||||
#else
|
||||
int seed = getpid();
|
||||
#endif
|
||||
g->fuzzTestSeed = seed;
|
||||
Warning(SourcePos(), "Using seed %d for fuzz testing",
|
||||
g->fuzzTestSeed);
|
||||
}
|
||||
#ifdef ISPC_IS_WINDOWS
|
||||
srand(g->fuzzTestSeed);
|
||||
#else
|
||||
srand48(g->fuzzTestSeed);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (outFileName == NULL && headerFileName == NULL)
|
||||
Warning(SourcePos(), "No output file or header file name specified. "
|
||||
"Program will be compiled and warnings/errors will "
|
||||
|
||||
39
sym.cpp
39
sym.cpp
@@ -354,3 +354,42 @@ SymbolTable::Print() {
|
||||
depth += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline int ispcRand() {
|
||||
#ifdef ISPC_IS_WINDOWS
|
||||
return rand();
|
||||
#else
|
||||
return lrand48();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Symbol *
|
||||
SymbolTable::RandomSymbol() {
|
||||
int v = ispcRand() % variables.size();
|
||||
if (variables[v]->size() == 0)
|
||||
return NULL;
|
||||
int count = ispcRand() % variables[v]->size();
|
||||
SymbolMapType::iterator iter = variables[v]->begin();
|
||||
while (count-- > 0) {
|
||||
++iter;
|
||||
Assert(iter != variables[v]->end());
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
|
||||
const Type *
|
||||
SymbolTable::RandomType() {
|
||||
int v = ispcRand() % types.size();
|
||||
if (types[v]->size() == 0)
|
||||
return NULL;
|
||||
int count = ispcRand() % types[v]->size();
|
||||
TypeMapType::iterator iter = types[v]->begin();
|
||||
while (count-- > 0) {
|
||||
++iter;
|
||||
Assert(iter != types[v]->end());
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
7
sym.h
7
sym.h
@@ -244,6 +244,13 @@ public:
|
||||
(Debugging method). */
|
||||
void Print();
|
||||
|
||||
/** Returns a random symbol from the symbol table. (It is not
|
||||
guaranteed that it is equally likely to return all symbols). */
|
||||
Symbol *RandomSymbol();
|
||||
|
||||
/** Returns a random type from the symbol table. */
|
||||
const Type *RandomType();
|
||||
|
||||
private:
|
||||
std::vector<std::string> closestTypeMatch(const char *str,
|
||||
bool structsVsEnums) const;
|
||||
|
||||
Reference in New Issue
Block a user