From d93e812f9f403f9b178dbe0960dd472e5a00f97a Mon Sep 17 00:00:00 2001 From: NovaRain Date: Thu, 14 Nov 2019 12:14:46 +0800 Subject: [PATCH] Merged changes from sfall 4.2.1 modderspack: * Added -m and -I options * Changed the search order for Include files for the parser DLL. * Removed embedded mcpp from Win2k build. --- compile.c | 70 ++- internal.H => internal.h | 2 +- mcpp_main.c | 12 +- mcpp_system.c | 46 +- noconfig.H => noconfig.h | 0 optimize.c | 1067 +++++++++++++++++++------------------- sslc.vcxproj | 8 +- 7 files changed, 639 insertions(+), 566 deletions(-) rename internal.H => internal.h (99%) rename noconfig.H => noconfig.h (100%) diff --git a/compile.c b/compile.c index 5124cfd..bae264f 100644 --- a/compile.c +++ b/compile.c @@ -7,10 +7,15 @@ #include "parse.h" #include +#ifdef BUILDING_DLL +int optimize = 0; +#else +int optimize = 1; // default for exe +#endif + int noinputwait = 0; int warnings = 1; int backwardcompat = 0; -int optimize = 0; int debug = 0; int preprocess_fullpath = 0; int dumpTree = 0; @@ -32,14 +37,19 @@ FILE *parseroutput; static void PrintLogo() { parseOutput("Startreck scripting language compiler (Fallout 2 sfall edition 4.2)\n\n" +#ifndef WIN2K "Preprocessing handled by mcpp 2.7.2\n" "Copyright (c) 1998, 2002-2008 Kiyoshi Matsui \n" - "All rights reserved.\n\n"); + "All rights reserved.\n\n" +#else + "Win2K/Lite version (no built-in preprocessor)\n\n" +#endif + ); } extern int warn_level; //the mcpp warning level -extern int mcpp_lib_main(FILE *fin, FILE *fout, const char* in_file, const char* dir); -//extern void set_a_dir(const char * dirname); +extern int mcpp_lib_main(FILE *fin, FILE *fout, const char* in_file, const char* dir, const char* def, const char* include_dir); +extern void mcpp_add_include_dir(char*); #ifndef BUILDING_DLL int main(int argc, char **argv) @@ -52,6 +62,8 @@ int main(int argc, char **argv) int preprocess=0; int onlypreprocess=0; + char* includeDir = NULL, *defMacro = NULL; + if (argc < 2) { PrintLogo(); parseOutput("Usage: compile {switches} filename [-o outputname] [filename [..]]\n"); @@ -59,13 +71,19 @@ int main(int argc, char **argv) parseOutput(" -n no warnings\n"); parseOutput(" -b use backward compatibility mode\n"); parseOutput(" -l no logo\n"); +#ifndef WIN2K parseOutput(" -p preprocess\n"); parseOutput(" -P preprocess only. (Don't generate .int)\n"); parseOutput(" -F write full file paths in #line directives\n"); - parseOutput(" -O optimize (0 - none, 1 - only remove unreferenced globals, 2 - full, 3 - full+experimental, don't use!)\n"); +#endif + parseOutput(" -O optimize (0 - none, 1 - only remove unreferenced globals (default), 2 - full, 3 - full+experimental, don't use!)\n"); parseOutput(" -d show debug info\n"); parseOutput(" -s enable short-circuit evaluation for boolean operators (AND, OR)\n"); parseOutput(" -D dump abstract syntax tree after optimizations\n"); +#ifndef WIN2K + parseOutput(" -m define a macro named \"macro\" for conditional compilation\n"); + parseOutput(" -I specify an additional directory to search for include files\n"); +#endif return 1; } @@ -87,13 +105,14 @@ int main(int argc, char **argv) case 'b': backwardcompat = 1; break; - case 'l': + case 'l': nologo=1; break; case 'O': - if (strlen(argv[1]) == 2) optimize = 2; + if (strlen(argv[1]) == 2) optimize = 2; // full else optimize = atoi(&argv[1][2]); break; +#ifndef WIN2K case 'P': onlypreprocess = 1; case 'p': @@ -102,12 +121,24 @@ int main(int argc, char **argv) case 'F': preprocess_fullpath = 1; break; +#endif case 'D': dumpTree = 1; break; case 's': shortCircuit = 1; break; +#ifndef WIN2K + case 'm': + defMacro = &argv[1][2]; + break; + case 'I': + if (!includeDir) + includeDir = &argv[1][2]; + else + mcpp_add_include_dir(&argv[1][2]); + break; +#endif default: parseOutput("Unknown option %c\n", argv[1][1]); } @@ -115,7 +146,7 @@ int main(int argc, char **argv) argv++; argc--; } - + // disabled - Fakels /*if(backwardcompat&&(optimize||preprocess)) { parseOutput("Invalid option combination; cannot run preprocess or optimization passes in backward compatibility mode\n"); return -1; @@ -124,7 +155,10 @@ int main(int argc, char **argv) if(!nologo) PrintLogo(); compilerErrorTotal = 0; - +#ifndef WIN2K + if (defMacro) parseOutput("Define macro: %s\n", defMacro); + if (includeDir) parseOutput("Set include directory: %s\n", includeDir); +#endif while(argv[1]) { file = argv[1]; argv++; @@ -173,7 +207,7 @@ int main(int argc, char **argv) } } } - +#ifndef WIN2K if(preprocess) { FILE *newfile; unsigned int letters; @@ -190,7 +224,7 @@ int main(int argc, char **argv) newfile=fopen(tmpbuf, "w+DT"); //#endif } - if(mcpp_lib_main(foo.file, newfile, buf.name, buf.name)) { + if(mcpp_lib_main(foo.file, newfile, buf.name, buf.name, defMacro, includeDir)) { parseOutput("*** An error occured during preprocessing of %s ***\n", buf.name); return 1; } @@ -198,6 +232,7 @@ int main(int argc, char **argv) rewind(newfile); foo.file=newfile; } +#endif if(!onlypreprocess) { parse(&foo, name); freeCurrentProgram(); @@ -214,8 +249,7 @@ int main(int argc, char **argv) getchar(); return 1; } - } - else { + } else { parseOutput("Warning: %s not found\n", file); } } @@ -226,8 +260,8 @@ int main(int argc, char **argv) #ifdef BUILDING_DLL static int inited=0; - -int _stdcall parse_main(const char *filePath, const char* origPath, const char* dir, int backMode) { +// old parser +int _stdcall parse_main(const char *filePath, const char* origPath, const char* dir/*, const char* def, const char* include_dir, int backMode*/) { InputStream foo; char tmpbuf[260]; //char cwd[1024]; @@ -239,12 +273,12 @@ int _stdcall parse_main(const char *filePath, const char* origPath, const char* FreeFileNames(); inited=0; } - +/* if (backMode) { backwardcompat = 1; lexClear(); } - +*/ foo.name=AddFileName(origPath); foo.file = fopen(filePath, "r"); @@ -258,7 +292,7 @@ int _stdcall parse_main(const char *filePath, const char* origPath, const char* compilerErrorTotal = 0; compilerSyntaxError = 0; preprocess_fullpath = 1; - if (mcpp_lib_main(foo.file, newfile, origPath, dir)) { + if (mcpp_lib_main(foo.file, newfile, origPath, dir, NULL, NULL)) { // prevent crash in old Script Editor - NR fclose(foo.file); fclose(newfile); if (parseroutput) diff --git a/internal.H b/internal.h similarity index 99% rename from internal.H rename to internal.h index 000ca32..7c95f81 100644 --- a/internal.H +++ b/internal.h @@ -454,7 +454,7 @@ extern int mcpp_fputs(const char *s, OUTDEST od); extern int mcpp_fprintf( OUTDEST od, const char *format, ...); /* system.c */ -extern void do_options(); +extern void do_options(const char* dir, const char* def, const char* include_dir, const char* second_dir); /* Process command line args */ extern void init_sys_macro( void); /* Define system-specific macro */ diff --git a/mcpp_main.c b/mcpp_main.c index c8a8165..95ae78d 100644 --- a/mcpp_main.c +++ b/mcpp_main.c @@ -250,6 +250,12 @@ static void devide_line( char * out); static void put_a_line( char * out); /* Put out the processed line */ +static char* second_include_dir = NULL; +void mcpp_add_include_dir(char* dir) /* added - Fakels */ +{ + second_include_dir = dir; +} + static void init_main( void) /* Initialize global variables on re-entering. */ { @@ -274,7 +280,9 @@ int mcpp_lib_main FILE *fin, FILE *fout, const char* in_file, - const char* dir + const char* dir, + const char* def, + const char* include_dir ) { const char * stdin_name = ""; @@ -303,7 +311,7 @@ int mcpp_lib_main inc_dirp = &null; /* Initialize to current (null) directory */ cur_fname = cur_fullname = "(predefined)"; /* For predefined macros */ init_defines(); /* Predefine macros */ - do_options(dir); /* Command line options */ + do_options(dir, def, include_dir, second_include_dir); /* Command line options */ init_sys_macro(); /* Initialize system-specific macros */ add_file( fp_in, NULL, in_file, in_file, FALSE); diff --git a/mcpp_system.c b/mcpp_system.c index 1ef1eec..ef9d81c 100644 --- a/mcpp_system.c +++ b/mcpp_system.c @@ -221,7 +221,10 @@ void init_system( void) #define OPTLISTLEN 80 void do_options( - const char* dir + const char* dir, + const char* def, + const char* include_dir, + const char* second_dir ) /* * Process command line arguments, called only at MCPP startup. @@ -245,8 +248,11 @@ void do_options( sprintf( cur_work_dir + strlen( cur_work_dir), "%c%c", PATH_DELIM, EOS); /* Append trailing path-delimiter */ - if (dir) - set_a_dir(dir); + if (dir) set_a_dir(dir); + if (include_dir) set_a_dir(include_dir); + if (second_dir) set_a_dir(second_dir); + /* define macros */ + if (def) def_list[def_cnt++] = (char*)def; /* Check consistency of specified options, set some variables */ chk_opts( sflag, trad); @@ -898,7 +904,13 @@ static int open_include( has_dir = has_dir_src || has_dir_fname || (**(infile->dirp) != EOS); } - +#ifdef BUILDING_DLL /* Reordered search include files for DLL (Fakels) */ + if (full_path) { + if (open_file( &null, NULL, filename, FALSE, FALSE, FALSE)) + return TRUE; + return FALSE; + } +#else if ((searchlocal && ((search_rule & CURRENT) || !has_dir)) || full_path) { /* * Look in local directory first. @@ -910,7 +922,7 @@ static int open_include( if (full_path) return FALSE; } - +#endif if (searchlocal && (search_rule & SOURCE) && has_dir) { /* * Look in local directory of source file. @@ -924,6 +936,16 @@ static int open_include( if (search_dir( filename, searchlocal, next)) return TRUE; +#ifdef BUILDING_DLL /* Reordered search include files for DLL (Fakels) */ + if ((searchlocal && ((search_rule & CURRENT) || !has_dir))) { + /* + * Look in local directory. + * Try to open filename relative to the "current directory". + */ + if (open_file( &null, NULL, filename, searchlocal, FALSE, FALSE)) + return TRUE; + } +#endif return FALSE; } @@ -1219,13 +1241,13 @@ static void cur_file( if (sharp_file) { /* Main input file */ name = file->filename; } else if (str_eq( file->filename, file->real_fname)) { - // sfall: added - if (preprocess_fullpath) { // - name = file->full_fname; // - } else { // end of added - sprintf( work_buf, "%s%s", *(file->dirp), cur_fname); - name = work_buf; - } + // sfall: added + if (preprocess_fullpath) { // + name = file->full_fname; // + } else { // end of added + sprintf( work_buf, "%s%s", *(file->dirp), cur_fname); + name = work_buf; + } } else { /* Changed by '#line fname' directive */ name = file->filename; } diff --git a/noconfig.H b/noconfig.h similarity index 100% rename from noconfig.H rename to noconfig.h diff --git a/optimize.c b/optimize.c index cadff37..428acfb 100644 --- a/optimize.c +++ b/optimize.c @@ -9,11 +9,11 @@ #include #include -#define Protect(a) if(_stricmp(c, a) == 0) return 1; +#define Protect(a) if (_stricmp(c, a) == 0) return 1; -#define F_OP(token,op) case token: out->floatData=fd1 op fd2; break; -#define F_IOP(token,op) case token: out->type=V_INT; out->intData=fd1 op fd2; break; -#define I_OP(token,op) case token: out->intData=in1->intData op in2->intData; break; +#define F_OP(token,op) case token: out->floatData = fd1 op fd2; break; +#define F_IOP(token,op) case token: out->type = V_INT; out->intData = fd1 op fd2; break; +#define I_OP(token,op) case token: out->intData = in1->intData op in2->intData; break; #define VU_FIRST_ASSIGN_IS_PURE 0x01 #define VU_FIRST_ASSIGN_IN_WHILE 0x02 @@ -29,28 +29,28 @@ static Program* currprogram; //Sanity checks. Should never be hit static void assert(int i) { - if(!i) + if (!i) parseError("ICE in optimizer."); } //Strip out some nods from a nodelist static void RemoveNodes(NodeList* nodes, int start, int count) { - memmove(&nodes->nodes[start], &nodes->nodes[start+count], (nodes->numNodes-(start+count))*sizeof(Node)); - nodes->numNodes-=count; + memmove(&nodes->nodes[start], &nodes->nodes[start + count], (nodes->numNodes - (start + count)) * sizeof(Node)); + nodes->numNodes -= count; //not much point reallocing } //Check if a node is a local variable, and return its id if so or -1 otherwise static int LookupVariable(const Node* node) { - assert(node->token==T_SYMBOL); - if(node->value.type!=P_LOCAL) return -1; + assert(node->token == T_SYMBOL); + if (node->value.type != P_LOCAL) return -1; return node->value.intData; } //Returns true if a token is known to have no side effects static int IsTokenPure(int token) { //TODO: Go through the whole list - switch(token) { + switch (token) { case T_TS_LEN_ARRAY: case T_TS_ATOI: case T_TS_ATOF: @@ -63,12 +63,12 @@ static int IsTokenPure(int token) { //Returns true if we can prove an expression has no side effects static int IsExpressionPure(const Node* node) { - assert(node->token==T_START_EXPRESSION); - while((++node)->token!=T_END_EXPRESSION) { - //if(node->token==T_START_EXPRESSION) return 0; - if(node->token>=T_END_CORE&&!IsTokenPure(node->token)) return 0; - if(node->token==T_SYMBOL&&node->value.type&P_PROCEDURE) { - if(node->value.type!=(P_LOCAL|P_PROCEDURE) || !(currprogram->procedures.procedures[node->value.intData].type&P_PURE)) return 0; + assert(node->token == T_START_EXPRESSION); + while ((++node)->token != T_END_EXPRESSION) { + //if (node->token == T_START_EXPRESSION) return 0; + if (node->token >= T_END_CORE && !IsTokenPure(node->token)) return 0; + if (node->token == T_SYMBOL && node->value.type & P_PROCEDURE) { + if (node->value.type != (P_LOCAL | P_PROCEDURE) || !(currprogram->procedures.procedures[node->value.intData].type & P_PURE)) return 0; } } return 1; @@ -83,76 +83,76 @@ typedef struct { } VarUsage; static void FindVarUsage(const Node* node, VarUsage* usage, int varCount) { - int depth=1, currstatement=0, i=0, whiledepth=0, ifdepth=0, var, expressiondepth; - memset(usage, 0, varCount*sizeof(VarUsage)); - assert(node->token==T_BEGIN); - while(depth) { + int depth = 1, currstatement = 0, i = 0, whiledepth = 0, ifdepth = 0, var, expressiondepth; + memset(usage, 0, varCount * sizeof(VarUsage)); + assert(node->token == T_BEGIN); + while (depth) { i++; - switch((++node)->token) { + switch ((++node)->token) { case T_BEGIN: depth++; break; case T_END: depth--; break; case T_START_STATEMENT: - if(ifdepth) ifdepth++; - if(!whiledepth) { - currstatement=i; - if(node[1].token==T_WHILE) { - whiledepth=1; - } else if(node[1].token==T_IF&&!ifdepth) { - ifdepth=1; + if (ifdepth) ifdepth++; + if (!whiledepth) { + currstatement = i; + if (node[1].token == T_WHILE) { + whiledepth = 1; + } else if (node[1].token == T_IF && !ifdepth) { + ifdepth = 1; } } else whiledepth++; break; case T_END_STATEMENT: - if(ifdepth) ifdepth--; - if(whiledepth) whiledepth--; + if (ifdepth) ifdepth--; + if (whiledepth) whiledepth--; break; case T_ASSIGN: case T_ASSIGN_ADD: case T_ASSIGN_SUB: case T_ASSIGN_MUL: case T_ASSIGN_DIV: - if((var=LookupVariable(&node[-1]))!=-1) { - int pure=IsExpressionPure(&node[1]); - usage[var].lastassign=currstatement; - if(whiledepth) usage[var].flags|=VU_LAST_ASSIGN_IN_WHILE; - else usage[var].flags&=~VU_LAST_ASSIGN_IN_WHILE; - if(pure) usage[var].flags|=VU_LAST_ASSIGN_IS_PURE; - if(!usage[var].firstuse) { - if(!usage[var].firstassign) { - usage[var].firstassign=currstatement; - if(whiledepth) usage[var].flags|=VU_FIRST_ASSIGN_IN_WHILE; - if(pure) { - usage[var].flags|=VU_FIRST_ASSIGN_IS_PURE; - if(!whiledepth&&!ifdepth&&node[2].token==T_CONSTANT&&node[3].token==T_END_EXPRESSION&&node[2].value.type!=V_STRING) { - usage[var].flags|=VU_FIRST_ASSIGN_TRANSFERABLE|VU_FIRST_ASSIGN_IS_DEAD; + if ((var = LookupVariable(&node[-1])) != -1) { + int pure = IsExpressionPure(&node[1]); + usage[var].lastassign = currstatement; + if (whiledepth) usage[var].flags |= VU_LAST_ASSIGN_IN_WHILE; + else usage[var].flags &= ~VU_LAST_ASSIGN_IN_WHILE; + if (pure) usage[var].flags |= VU_LAST_ASSIGN_IS_PURE; + if (!usage[var].firstuse) { + if (!usage[var].firstassign) { + usage[var].firstassign = currstatement; + if (whiledepth) usage[var].flags |= VU_FIRST_ASSIGN_IN_WHILE; + if (pure) { + usage[var].flags |= VU_FIRST_ASSIGN_IS_PURE; + if (!whiledepth && !ifdepth && node[2].token == T_CONSTANT && node[3].token == T_END_EXPRESSION && node[2].value.type != V_STRING) { + usage[var].flags |= VU_FIRST_ASSIGN_TRANSFERABLE | VU_FIRST_ASSIGN_IS_DEAD; } } - } else if(!whiledepth && !ifdepth) { - if(usage[var].flags&VU_FIRST_ASSIGN_IS_PURE&&node->token==T_ASSIGN) usage[var].flags|=VU_FIRST_ASSIGN_IS_DEAD; - } else if(!pure&&currstatement==usage[var].firstassign) usage[var].flags&=~VU_FIRST_ASSIGN_IS_PURE; + } else if (!whiledepth && !ifdepth) { + if (usage[var].flags & VU_FIRST_ASSIGN_IS_PURE && node->token == T_ASSIGN) usage[var].flags |= VU_FIRST_ASSIGN_IS_DEAD; + } else if (!pure && currstatement == usage[var].firstassign) usage[var].flags &= ~VU_FIRST_ASSIGN_IS_PURE; } - if(node->token!=T_ASSIGN) { - usage[var].lastuse=currstatement; - if(whiledepth) usage[var].flags|=VU_LAST_READ_IN_WHILE; - else usage[var].flags&=~VU_LAST_READ_IN_WHILE; - if(!usage[var].firstuse) { - usage[var].firstuse=currstatement; - if(whiledepth) usage[var].flags|=VU_FIRST_READ_IN_WHILE; + if (node->token != T_ASSIGN) { + usage[var].lastuse = currstatement; + if (whiledepth) usage[var].flags |= VU_LAST_READ_IN_WHILE; + else usage[var].flags &= ~VU_LAST_READ_IN_WHILE; + if (!usage[var].firstuse) { + usage[var].firstuse = currstatement; + if (whiledepth) usage[var].flags |= VU_FIRST_READ_IN_WHILE; } } } break; case T_START_EXPRESSION: - expressiondepth=1; - while(expressiondepth) { + expressiondepth = 1; + while (expressiondepth) { i++; - switch((++node)->token) { + switch ((++node)->token) { case T_START_EXPRESSION: expressiondepth++; break; case T_END_EXPRESSION: expressiondepth--; break; case T_SYMBOL: - if((var=LookupVariable(node))!=-1) { - usage[var].lastuse=currstatement; - if(whiledepth) usage[var].flags|=VU_LAST_READ_IN_WHILE; - else usage[var].flags&=~VU_LAST_READ_IN_WHILE; - if(!usage[var].firstuse) { - usage[var].firstuse=currstatement; - if(whiledepth) usage[var].flags|=VU_FIRST_READ_IN_WHILE; + if ((var = LookupVariable(node)) != -1) { + usage[var].lastuse = currstatement; + if (whiledepth) usage[var].flags |= VU_LAST_READ_IN_WHILE; + else usage[var].flags &= ~VU_LAST_READ_IN_WHILE; + if (!usage[var].firstuse) { + usage[var].firstuse = currstatement; + if (whiledepth) usage[var].flags |= VU_FIRST_READ_IN_WHILE; } } } @@ -160,26 +160,26 @@ static void FindVarUsage(const Node* node, VarUsage* usage, int varCount) { break; } } - assert(node->token==T_END); + assert(node->token == T_END); } static int isValidBinaryOp(int op) { - return op=='+'||op=='-'||op=='*'||op=='/'||op==T_AND||op==T_OR||op==T_BWAND||op==T_BWOR||op==T_BWXOR|| - op=='>'||op=='<'||op==T_EQUAL||op==T_NOT_EQUAL||op==T_LESS_EQUAL||op==T_GREATER_EQUAL; + return op == '+' || op == '-' || op == '*' || op == '/' || op == T_AND || op == T_OR || op == T_BWAND || op == T_BWOR || op == T_BWXOR || + op == '>' || op == '<' || op == T_EQUAL || op == T_NOT_EQUAL || op == T_LESS_EQUAL || op == T_GREATER_EQUAL; } //Calculate the result of a constant operation (doesn't handle strings, which would require namespace modifications) static void PerformConstOp(const Value* in1, const Value* in2, Value* out, int op, const Node* node) { int isfloat; assert(isValidBinaryOp(op)); - assert(in1->type==V_INT||in1->type==V_FLOAT); - assert(in2->type==V_INT||in2->type==V_FLOAT); - isfloat = in1->type==V_FLOAT || in2->type==V_FLOAT; - if(isfloat) { - float fd1=in1->type==V_FLOAT?in1->floatData:(float)in1->intData; - float fd2=in2->type==V_FLOAT?in2->floatData:(float)in2->intData; - out->type=V_FLOAT; - switch(op) { + assert(in1->type == V_INT || in1->type == V_FLOAT); + assert(in2->type == V_INT || in2->type == V_FLOAT); + isfloat = in1->type == V_FLOAT || in2->type == V_FLOAT; + if (isfloat) { + float fd1 = in1->type == V_FLOAT ? in1->floatData : (float)in1->intData; + float fd2 = in2->type == V_FLOAT ? in2->floatData : (float)in2->intData; + out->type = V_FLOAT; + switch (op) { F_OP('+', +) F_OP('-', -) F_OP('*', *) @@ -191,32 +191,32 @@ static void PerformConstOp(const Value* in1, const Value* in2, Value* out, int o F_IOP(T_LESS_EQUAL, <=) F_IOP(T_GREATER_EQUAL, >=) case T_AND: - out->type=V_INT; - out->intData=fd1!=0.0 && fd2!=0.0; + out->type = V_INT; + out->intData = (fd1 != 0.0) && (fd2 != 0.0); break; case T_OR: - out->type=V_INT; - out->intData=fd1!=0.0 || fd2!=0.0; + out->type = V_INT; + out->intData = (fd1 != 0.0) || (fd2 != 0.0); break; case T_BWAND: - out->type=V_INT; + out->type = V_INT; parseWarningAtNode(node, "Optimizer encountered a bitwise operation on a float constant"); - out->intData=in1->intData & in2->intData; + out->intData = in1->intData & in2->intData; break; case T_BWOR: - out->type=V_INT; + out->type = V_INT; parseWarningAtNode(node, "Optimizer encountered a bitwise operation on a float constant"); - out->intData=in1->intData | in2->intData; + out->intData = in1->intData | in2->intData; break; case T_BWXOR: - out->type=V_INT; + out->type = V_INT; parseWarningAtNode(node, "Optimizer encountered a bitwise operation on a float constant"); - out->intData=in1->intData ^ in2->intData; + out->intData = in1->intData ^ in2->intData; break; } } else { - out->type=V_INT; - switch(op) { + out->type = V_INT; + switch (op) { I_OP('+', +) I_OP('-', -) I_OP('*', *) @@ -238,56 +238,56 @@ static void PerformConstOp(const Value* in1, const Value* in2, Value* out, int o static int ConstantFolding(NodeList* _nodes) { int i, token, matched=0; - Node* nodes=_nodes->nodes; - for(i=2;i<_nodes->numNodes;i++) { - token=nodes[i].token; - if(isValidBinaryOp(token)) { - if(nodes[i-1].token==T_CONSTANT && nodes[i-2].token==T_CONSTANT && nodes[i-1].value.type!=V_STRING && nodes[i-2].value.type!=V_STRING) { + Node* nodes = _nodes->nodes; + for (i = 2; i < _nodes->numNodes; i++) { + token = nodes[i].token; + if (isValidBinaryOp(token)) { + if (nodes[i - 1].token == T_CONSTANT && nodes[i - 2].token == T_CONSTANT && nodes[i - 1].value.type != V_STRING && nodes[i - 2].value.type != V_STRING) { parseMessageAtNode(&nodes[i], "Folding constant binary expression"); - matched=1; - PerformConstOp(&nodes[i-2].value, &nodes[i-1].value, &nodes[i].value, token, &nodes[i]); - nodes[i].token=T_CONSTANT; - RemoveNodes(_nodes, i-2, 2); + matched = 1; + PerformConstOp(&nodes[i - 2].value, &nodes[i - 1].value, &nodes[i].value, token, &nodes[i]); + nodes[i].token = T_CONSTANT; i -= 2; + RemoveNodes(_nodes, i, 2); }/* AND/OR were changed in the tree - else if(token==T_AND||token==T_OR) { - if((nodes[i-1].token==T_CONSTANT && nodes[i-1].value.type!=V_STRING) || (nodes[i-2].token==T_CONSTANT && nodes[i-2].value.type!=V_STRING)) { - if((nodes[i-1].token==T_SYMBOL&&!(nodes[i-1].value.type&P_PROCEDURE)) || (nodes[i-2].token==T_SYMBOL&&!(nodes[i-1].value.type&P_PROCEDURE))) { - int value, found=0; - if(nodes[i-1].token==T_CONSTANT && nodes[i-1].value.type!=V_STRING) value=nodes[i-1].value.intData; - else value=nodes[i-2].value.intData; - if(!value && token==T_AND) { - found=1; - } else if(value && token==T_OR) { - found=2; + else if (token == T_AND || token == T_OR) { + if ((nodes[i - 1].token == T_CONSTANT && nodes[i - 1].value.type != V_STRING) || (nodes[i - 2].token == T_CONSTANT && nodes[i - 2].value.type != V_STRING)) { + if ((nodes[i - 1].token == T_SYMBOL && !(nodes[i - 1].value.type & P_PROCEDURE)) || (nodes[i - 2].token == T_SYMBOL && !(nodes[i - 1].value.type & P_PROCEDURE))) { + int value, found = 0; + if (nodes[i - 1].token == T_CONSTANT && nodes[i - 1].value.type != V_STRING) value = nodes[i - 1].value.intData; + else value = nodes[i - 2].value.intData; + if (!value && token == T_AND) { + found = 1; + } else if (value && token == T_OR) { + found = 2; } - if(found) { + if (found) { parseMessageAtNode(&nodes[i], "Folding semi-constant binary expression"); - nodes[i].token=T_CONSTANT; - nodes[i].value.type=V_INT; - nodes[i].value.intData=found-1; - RemoveNodes(_nodes, i-2, 2); + nodes[i].token = T_CONSTANT; + nodes[i].value.type = V_INT; + nodes[i].value.intData = found - 1; + RemoveNodes(_nodes, i - 2, 2); i -= 2; } } } }*/ - } else if(token==T_NOT||token==T_BWNOT||token==T_NEGATE) { - if(nodes[i-1].token==T_CONSTANT && nodes[i-1].value.type!=V_STRING) { + } else if (token == T_NOT || token == T_BWNOT || token == T_NEGATE) { + if (nodes[i - 1].token == T_CONSTANT && nodes[i - 1].value.type != V_STRING) { parseMessageAtNode(&nodes[i], "Folding constant unary expression"); - matched=1; - if(token==T_NOT) { - nodes[i-1].value.type=V_INT; - nodes[i-1].value.intData=!nodes[i-1].value.intData; - } else if (token==T_BWNOT) { - if(nodes[i-1].value.type!=V_INT) parseWarningAtNode(&nodes[i-1], "Optimizer encountered a bitwise operation on a float constant"); - nodes[i-1].value.type=V_INT; - nodes[i-1].value.intData = ~nodes[i-1].value.intData; + matched = 1; + if (token == T_NOT) { + nodes[i - 1].value.type = V_INT; + nodes[i - 1].value.intData = !nodes[i - 1].value.intData; + } else if (token == T_BWNOT) { + if (nodes[i - 1].value.type != V_INT) parseWarningAtNode(&nodes[i - 1], "Optimizer encountered a bitwise operation on a float constant"); + nodes[i - 1].value.type = V_INT; + nodes[i - 1].value.intData = ~nodes[i - 1].value.intData; } else { - if (nodes[i-1].value.type==V_INT) - nodes[i-1].value.intData = -nodes[i-1].value.intData; + if (nodes[i - 1].value.type == V_INT) + nodes[i - 1].value.intData = -nodes[i - 1].value.intData; else - nodes[i-1].value.floatData = -nodes[i-1].value.floatData; + nodes[i - 1].value.floatData = -nodes[i - 1].value.floatData; } RemoveNodes(_nodes, i, 1); i -= 1; @@ -298,40 +298,47 @@ static int ConstantFolding(NodeList* _nodes) { } static int ConstantPropagateExpression(Node* nodes, Variable* vars, Value* values, int varCount, int *_i) { - int expressiondepth=1, matched=0, token, var, i=*_i; - assert(nodes[i].token==T_START_EXPRESSION); - while(expressiondepth) { + int expressiondepth = 1, matched = 0, token, var, i = *_i; + assert(nodes[i].token == T_START_EXPRESSION); + while (expressiondepth) { token = nodes[++i].token; - if(token==T_START_EXPRESSION) expressiondepth++; - else if(token==T_END_EXPRESSION) expressiondepth--; - else if(token==T_SYMBOL) { - if((var=LookupVariable(&nodes[i]))!=-1) { - if(values[var].type!=-1) { - nodes[i].token=T_CONSTANT; - nodes[i].value=values[var]; + if (token == T_START_EXPRESSION) expressiondepth++; + else if (token == T_END_EXPRESSION) expressiondepth--; + else if (token == T_SYMBOL) { + if ((var = LookupVariable(&nodes[i])) != -1) { + if (values[var].type != -1) { + nodes[i].token = T_CONSTANT; + nodes[i].value = values[var]; parseMessageAtNode(&nodes[i], "propagating constant %d", values[var].intData); - matched=1; + matched = 1; } } } } - assert(nodes[i].token==T_END_EXPRESSION); - *_i=i; + assert(nodes[i].token == T_END_EXPRESSION); + *_i = i; return matched; } static int* FindAssignmentsInBlock(const Node* nodes, const Variable* vars, int varCount) { - int* results=(int*)calloc(1, varCount*4); - int statementdepth=1, var; - assert(nodes->token==T_START_STATEMENT); - while(statementdepth) { - switch(nodes->token) { - case T_START_STATEMENT: statementdepth++; break; - case T_END_STATEMENT: statementdepth--; break; - case T_ASSIGN: case T_ASSIGN_ADD: case T_ASSIGN_SUB: - case T_ASSIGN_MUL: case T_ASSIGN_DIV: - if(nodes[-1].token==T_SYMBOL&&(var=LookupVariable(&nodes[-1]))!=-1) { - results[var]=1; + int* results = (int*)calloc(1, varCount * 4); + int statementdepth = 1, var; + assert(nodes->token == T_START_STATEMENT); + while (statementdepth) { + switch (nodes->token) { + case T_START_STATEMENT: + statementdepth++; + break; + case T_END_STATEMENT: + statementdepth--; + break; + case T_ASSIGN: + case T_ASSIGN_ADD: + case T_ASSIGN_SUB: + case T_ASSIGN_MUL: + case T_ASSIGN_DIV: + if (nodes[-1].token == T_SYMBOL && (var = LookupVariable(&nodes[-1])) != -1) { + results[var] = 1; } break; } @@ -341,159 +348,166 @@ static int* FindAssignmentsInBlock(const Node* nodes, const Variable* vars, int } static int ConstantPropagateBlock(Node* nodes, int *_i, Variable* vars, Value* values, int varCount) { - int i=_i?*_i:0, token, var, matched=0, blockdepth=1, blockbegin, blockend, j; - assert(nodes->token==T_BEGIN||nodes->token==T_START_STATEMENT); - if(nodes[i].token==T_BEGIN) { - blockbegin=T_BEGIN; - blockend=T_END; + int i = _i ? *_i : 0, + matched = 0, + blockdepth = 1, + token, var, blockbegin, blockend, j; + + assert(nodes->token == T_BEGIN || nodes->token == T_START_STATEMENT); + + if (nodes[i].token == T_BEGIN) { + blockbegin = T_BEGIN; + blockend = T_END; } else { - blockbegin=T_START_STATEMENT; - blockend=T_END_STATEMENT; + blockbegin = T_START_STATEMENT; + blockend = T_END_STATEMENT; } + i++; - while(1) { - token=nodes[i].token; - if(token==blockbegin) blockdepth++; - else if(token==blockend) { - if(!--blockdepth) break; - } else if(token==T_ASSIGN || token==T_ASSIGN_ADD ||token==T_ASSIGN_SUB || token==T_ASSIGN_MUL || token==T_ASSIGN_DIV) { - if((var=LookupVariable(&nodes[i-1]))!=-1) { - if(nodes[i+1].token==T_START_EXPRESSION && nodes[i+2].token==T_CONSTANT && nodes[i+3].token==T_END_EXPRESSION) { - if(token==T_ASSIGN) values[var]=nodes[i+2].value; - else if(values[var].type!=-1) { - switch(token) { - case T_ASSIGN_ADD: token='+'; break; - case T_ASSIGN_SUB: token='-'; break; - case T_ASSIGN_MUL: token='*'; break; - case T_ASSIGN_DIV: token='/'; break; + while (1) { + token = nodes[i].token; + if (token == blockbegin) blockdepth++; + else if (token == blockend) { + if (!--blockdepth) break; + } else if (token == T_ASSIGN || token == T_ASSIGN_ADD ||token == T_ASSIGN_SUB || token == T_ASSIGN_MUL || token == T_ASSIGN_DIV) { + if ((var = LookupVariable(&nodes[i - 1])) != -1) { + if (nodes[i + 1].token == T_START_EXPRESSION && nodes[i + 2].token == T_CONSTANT && nodes[i + 3].token == T_END_EXPRESSION) { + if (token == T_ASSIGN) + values[var] = nodes[i + 2].value; + else if (values[var].type != -1) { + switch (token) { + case T_ASSIGN_ADD: token = '+'; break; + case T_ASSIGN_SUB: token = '-'; break; + case T_ASSIGN_MUL: token = '*'; break; + case T_ASSIGN_DIV: token = '/'; break; } - PerformConstOp(&values[var], &nodes[i+2].value, &values[var], token, &nodes[i]); + PerformConstOp(&values[var], &nodes[i + 2].value, &values[var], token, &nodes[i]); } } else { - values[var].type=-1; + values[var].type = -1; } } - } else if(token==T_IF) { - int *aif=0, *aelse=0; - Value* backup=(Value*)malloc(varCount*sizeof(Value)); - memcpy(backup, values, varCount*sizeof(Value)); + } else if (token == T_IF) { + int *aif = 0, *aelse = 0; + Value* backup = (Value*)malloc(varCount * sizeof(Value)); + memcpy(backup, values, varCount * sizeof(Value)); i++; - matched|=ConstantPropagateExpression(nodes, vars, values, varCount, &i); + matched |= ConstantPropagateExpression(nodes, vars, values, varCount, &i); i++; - assert(nodes[i++].token==T_THEN); - aif=FindAssignmentsInBlock(&nodes[i], vars, varCount); + assert(nodes[i++].token == T_THEN); + aif = FindAssignmentsInBlock(&nodes[i], vars, varCount); ConstantPropagateBlock(nodes, &i, vars, values, varCount); - if(nodes[i+1].token==T_ELSE) { - i+=2; - memcpy(values, backup, varCount*sizeof(Value)); - aelse=FindAssignmentsInBlock(&nodes[i], vars, varCount); - for(j=0;jtoken!=T_DO) nodes2++; - invalidate=FindAssignmentsInBlock(nodes2+1, vars, varCount); - for(j=0;jtoken != T_DO) nodes2++; + invalidate = FindAssignmentsInBlock(nodes2 + 1, vars, varCount); + for (j = 0; j < varCount; j++) if (invalidate[j]) values[j].type = -1; + } else if (token == T_START_EXPRESSION) { + matched |= ConstantPropagateExpression(nodes, vars, values, varCount, &i); } i++; } - assert(nodes[i].token==blockend); - if(_i) *_i=i; + assert(nodes[i].token == blockend); + if (_i) *_i = i; return matched; } static int ConstantPropagation(NodeList* _nodes, Variable* vars, Value* values, int varCount, int numArgs) { int i; - for(i=0;inodes, 0, vars, values, varCount); } -#define SkipStatement { statementdepth=1; \ - assert(nodes[i-1].token==T_START_STATEMENT); \ - while(statementdepth) { if(nodes[i].token==T_START_STATEMENT) statementdepth++; \ - else if(nodes[i].token==T_END_STATEMENT) statementdepth--; \ - i++; \ +#define SkipStatement { statementdepth = 1; \ + assert(nodes[i - 1].token == T_START_STATEMENT); \ + while (statementdepth) { if (nodes[i].token == T_START_STATEMENT) statementdepth++; \ + else if (nodes[i].token == T_END_STATEMENT) statementdepth--; \ + i++; \ }} static void EatStatement(NodeList* _nodes, int start) { - int statementdepth=1, i=start+1; - Node* nodes=_nodes->nodes; - assert(nodes[start].token==T_START_STATEMENT); + int statementdepth = 1, i = start + 1; + Node* nodes = _nodes->nodes; + assert(nodes[start].token == T_START_STATEMENT); SkipStatement; RemoveNodes(_nodes, start, i-start); } static void EatAssignsInWhile(NodeList* _nodes, int start, int varid) { - int statementdepth=1; - Node* nodes=_nodes->nodes; - assert(nodes[start++].token==T_START_STATEMENT); - assert(nodes[start].token==T_WHILE); - while(statementdepth) { - switch(nodes[++start].token) { + int statementdepth = 1; + Node* nodes = _nodes->nodes; + assert(nodes[start++].token == T_START_STATEMENT); + assert(nodes[start].token == T_WHILE); + while (statementdepth) { + switch (nodes[++start].token) { case T_START_STATEMENT: - if(nodes[start+1].token==T_SYMBOL&&nodes[start+2].token>=T_ASSIGN&&nodes[start+2].token<=T_ASSIGN_DIV&&LookupVariable(&nodes[start+1])==varid) { + if (nodes[start + 1].token == T_SYMBOL && nodes[start + 2].token >= T_ASSIGN && nodes[start + 2].token <= T_ASSIGN_DIV && LookupVariable(&nodes[start + 1]) == varid) { EatStatement(_nodes, start--); } else statementdepth++; break; case T_END_STATEMENT: statementdepth--; break; } } - assert(nodes[start].token==T_END_STATEMENT); + assert(nodes[start].token == T_END_STATEMENT); } static void EatDeadStore(NodeList* _nodes, int start, int var) { - Node* nodes=_nodes->nodes; - assert(nodes[start].token==T_START_STATEMENT); - if(nodes[start+1].token==T_WHILE) { - parseMessageAtNode(&nodes[start+1], "Eating dead stores to variable %d in while loop", var); + Node* nodes = _nodes->nodes; + assert(nodes[start].token == T_START_STATEMENT); + if (nodes[start + 1].token == T_WHILE) { + parseMessageAtNode(&nodes[start + 1], "Eating dead stores to variable %d in while loop", var); EatAssignsInWhile(_nodes, start, var); } else { - parseMessageAtNode(&nodes[start+1], "Eating dead store to variable %d", var); + parseMessageAtNode(&nodes[start + 1], "Eating dead store to variable %d", var); EatStatement(_nodes, start); } } static int DeadStoreRemoval(NodeList* _nodes, VariableList* vars, VarUsage* usage) { - int i, matched1, matched2=0; - Node* nodes=_nodes->nodes; - while(1) { - matched1=0; + int i, matched1, matched2 = 0; + Node* nodes = _nodes->nodes; + while (1) { + matched1 = 0; FindVarUsage(nodes, usage, vars->numVariables); - for(i=0;inumVariables;i++) { - if(usage[i].flags&VU_FIRST_ASSIGN_IS_DEAD) { - if(usage[i].flags&VU_FIRST_ASSIGN_TRANSFERABLE) { + for (i = 0; i < vars->numVariables; i++) { + if (usage[i].flags & VU_FIRST_ASSIGN_IS_DEAD) { + if (usage[i].flags & VU_FIRST_ASSIGN_TRANSFERABLE) { parseMessageAtNode(&nodes[usage[i].firstassign], "Using constant variable store for initializer"); - assert(nodes[usage[i].firstassign + 4].token==T_CONSTANT); - vars->variables[i].value=nodes[usage[i].firstassign + 4].value; + assert(nodes[usage[i].firstassign + 4].token == T_CONSTANT); + vars->variables[i].value = nodes[usage[i].firstassign + 4].value; } EatDeadStore(_nodes, usage[i].firstassign, i); - matched1=1; + matched1 = 1; break; - } else if(usage[i].lastassign>=usage[i].lastuse && usage[i].flags&VU_LAST_ASSIGN_IS_PURE) { - if(nodes[usage[i].lastassign+1].token!=T_WHILE || usage[i].lastassign>usage[i].lastuse) { + } else if (usage[i].lastassign >= usage[i].lastuse && usage[i].flags & VU_LAST_ASSIGN_IS_PURE) { + if (nodes[usage[i].lastassign + 1].token != T_WHILE || usage[i].lastassign > usage[i].lastuse) { //Pretty sure I don't need the do check here - if(nodes[usage[i].lastassign-1].token!=T_THEN&&nodes[usage[i].lastassign-1].token!=T_ELSE&&nodes[usage[i].lastassign-1].token!=T_DO) { + if (nodes[usage[i].lastassign - 1].token != T_THEN && nodes[usage[i].lastassign - 1].token != T_ELSE && nodes[usage[i].lastassign - 1].token != T_DO) { EatDeadStore(_nodes, usage[i].lastassign, i); - matched1=1; + matched1 = 1; break; } } } } - if(matched1) { - matched2=1; + if (matched1) { + matched2 = 1; continue; } break; @@ -502,65 +516,65 @@ static int DeadStoreRemoval(NodeList* _nodes, VariableList* vars, VarUsage* usag } static int DeadCodeRemoval(NodeList* _nodes) { - int i, statementdepth, takebranch, matched=0; - Node* nodes=_nodes->nodes; + int i, statementdepth, takebranch, matched = 0; + Node* nodes = _nodes->nodes; //First look for constant if branches - for(i=0;i<_nodes->numNodes;i++) { + for (i = 0; i < _nodes->numNodes; i++) { if (nodes[i].token == T_IF && nodes[i - 1].token == T_START_STATEMENT) { - if(nodes[i+1].token==T_START_EXPRESSION && nodes[i+2].token==T_CONSTANT && nodes[i+3].token==T_END_EXPRESSION) { - int back=i-1; - matched=1; - //Need to check if fallout considers 'if("bingle")' and 'if("")' to be 1 or 0 - takebranch=nodes[i+2].value.intData; + if (nodes[i + 1].token == T_START_EXPRESSION && nodes[i + 2].token == T_CONSTANT && nodes[i + 3].token == T_END_EXPRESSION) { + int back=i - 1; + matched = 1; + //Need to check if fallout considers 'if ("bingle")' and 'if ("")' to be 1 or 0 + takebranch = nodes[i + 2].value.intData; RemoveNodes(_nodes, --i, 6); //start statement, if, start expression, const, end expression, then - assert(nodes[i].token==T_START_STATEMENT); - if(takebranch) { - int back2=i++, tmp; + assert(nodes[i].token == T_START_STATEMENT); + if (takebranch) { + int back2 = i++, tmp; parseMessageAtNode(&nodes[i], "Eliminating constant if expression (true)"); - assert(nodes[i].token==T_BEGIN); + assert(nodes[i].token == T_BEGIN); SkipStatement; - assert(nodes[i-2].token==T_END); - RemoveNodes(_nodes, i-2, 2); //end end statement - tmp=i; - i=back2; - assert(nodes[i].token==T_START_STATEMENT); - assert(nodes[i+1].token==T_BEGIN); + assert(nodes[i - 2].token == T_END); + RemoveNodes(_nodes, i - 2, 2); //end end statement + tmp = i; + i = back2; + assert(nodes[i].token == T_START_STATEMENT); + assert(nodes[i + 1].token == T_BEGIN); RemoveNodes(_nodes, i, 2); //begin begin statement - i=tmp-4; - if(nodes[i].token==T_ELSE) { + i = tmp - 4; + if (nodes[i].token == T_ELSE) { RemoveNodes(_nodes, i, 1); EatStatement(_nodes, i); } } else { parseMessageAtNode(&nodes[i], "Eliminating constant if expression (false)"); EatStatement(_nodes, i); - if(nodes[i].token==T_ELSE) { - int back2=i++, tmp; - RemoveNodes(_nodes, i-1, 1); //else - assert(nodes[i].token==T_BEGIN); + if (nodes[i].token == T_ELSE) { + int back2 = i++, tmp; + RemoveNodes(_nodes, i - 1, 1); //else + assert(nodes[i].token == T_BEGIN); SkipStatement; - assert(nodes[i-2].token==T_END); - RemoveNodes(_nodes, i-2, 2); //end end statement - tmp=i; - i=back2; - assert(nodes[i].token==T_START_STATEMENT); - assert(nodes[i+1].token==T_BEGIN); + assert(nodes[i - 2].token == T_END); + RemoveNodes(_nodes, i - 2, 2); //end end statement + tmp = i; + i = back2; + assert(nodes[i].token == T_START_STATEMENT); + assert(nodes[i + 1].token == T_BEGIN); RemoveNodes(_nodes, i, 2); //else begin statement begin - i=tmp-4; + i = tmp - 4; } } - assert(nodes[i].token==T_END_STATEMENT); + assert(nodes[i].token == T_END_STATEMENT); RemoveNodes(_nodes, i, 1); //The final end statement - i=back; + i = back; } } } //Next strip out anything following returns, breaks and continue - for(i=0;i<_nodes->numNodes;i++) { - if(nodes[i].token==T_RETURN||nodes[i].token==T_BREAK||nodes[i].token==T_CONTINUE) { - //if (nodes[i].token==T_RETURN) + for (i = 0; i < _nodes->numNodes; i++) { + if (nodes[i].token == T_RETURN||nodes[i].token == T_BREAK||nodes[i].token == T_CONTINUE) { + //if (nodes[i].token == T_RETURN) SkipStatement; - while(nodes[i].token==T_START_STATEMENT) { + while (nodes[i].token == T_START_STATEMENT) { parseMessageAtNode(&nodes[i], "Eating statement hidden by return"); EatStatement(_nodes, i); matched=1; @@ -568,48 +582,48 @@ static int DeadCodeRemoval(NodeList* _nodes) { } } //Finally look for empty if blocks and remove them if the expression is pure - for(i=0;i<_nodes->numNodes-5;i++) { - if(nodes[i].token==T_THEN&&nodes[i+3].token==T_END&&nodes[i+4].token==T_END_STATEMENT&&nodes[i+5].token!=T_ELSE) { - int back=i,expressiondepth=1; - assert(nodes[i+1].token==T_START_STATEMENT); - assert(nodes[i+2].token==T_BEGIN); - assert(nodes[i-1].token==T_END_EXPRESSION); - i-=2; - while(expressiondepth) { - if(nodes[i].token==T_START_EXPRESSION) expressiondepth--; - else if(nodes[i].token==T_END_EXPRESSION) expressiondepth++; + for (i = 0; i < _nodes->numNodes - 5; i++) { + if (nodes[i].token == T_THEN&&nodes[i+3].token == T_END&&nodes[i+4].token == T_END_STATEMENT&&nodes[i+5].token!=T_ELSE) { + int back = i, expressiondepth = 1; + assert(nodes[i + 1].token == T_START_STATEMENT); + assert(nodes[i + 2].token == T_BEGIN); + assert(nodes[i - 1].token == T_END_EXPRESSION); + i -= 2; + while (expressiondepth) { + if (nodes[i].token == T_START_EXPRESSION) expressiondepth--; + else if (nodes[i].token == T_END_EXPRESSION) expressiondepth++; i--; } - assert(nodes[i].token==T_IF); - assert(nodes[--i].token==T_START_STATEMENT); - if(IsExpressionPure(&nodes[i+2])) { + assert(nodes[i].token == T_IF); + assert(nodes[--i].token == T_START_STATEMENT); + if (IsExpressionPure(&nodes[i + 2])) { parseMessageAtNode(&nodes[i], "Eating empty if block"); EatStatement(_nodes, i); - matched=1; + matched = 1; } else { parseWarningAtNode(&nodes[i], "Optimizer found an empty if block, but could not remove it because the expression could not be confirmed as pure"); } - i=back; + i = back; } - if(nodes[i].token==T_ELSE&&nodes[i+3].token==T_END&&nodes[i+4].token==T_END_STATEMENT) { - int back=i,expressiondepth=1; - assert(nodes[i+1].token==T_START_STATEMENT); - assert(nodes[i+2].token==T_BEGIN); - assert(nodes[i-1].token==T_END_STATEMENT); + if (nodes[i].token == T_ELSE && nodes[i + 3].token == T_END && nodes[i + 4].token == T_END_STATEMENT) { + int back = i, expressiondepth = 1; + assert(nodes[i + 1].token == T_START_STATEMENT); + assert(nodes[i + 2].token == T_BEGIN); + assert(nodes[i - 1].token == T_END_STATEMENT); parseMessageAtNode(&nodes[i], "Eating empty else block"); RemoveNodes(_nodes, i, 1); EatStatement(_nodes, i); - matched=1; + matched = 1; } } return matched; } static int CanCombine(VarUsage *u1, VarUsage *u2) { - int u1min=u1->firstassignfirstuse?u1->firstassign:u1->firstuse; - int u2max=u2->lastassign>u2->lastuse?u2->lastassign:u2->lastuse; - if(u1minu2max) return 1; + int u1min = u1->firstassign < u1->firstuse ? u1->firstassign : u1->firstuse; + int u2max = u2->lastassign > u2->lastuse ? u2->lastassign : u2->lastuse; + if (u1min < u2max) return 0; + if (u1min > u2max) return 1; //TODO: If they're equal, if we're in a while loop return 0, otherwise if one is an assign and the other is part of the expression we can probably combine return 0; } @@ -618,12 +632,12 @@ static void VariableReuse(NodeList* _nodes, VariableList* vars, int numArgs, Var int i, j, k; Node* nodes=_nodes->nodes; FindVarUsage(nodes, usage, vars->numVariables); - for(i=vars->numVariables-1;i>=numArgs;i--) { - for(j=0;jnumVariables-1;i>=numArgs;i--) { + for (j=0;jnumNodes;k++) { - if(nodes[k].token==T_SYMBOL&&LookupVariable(&nodes[k])==i) nodes[k].value.intData=j; + for (k=0;k<_nodes->numNodes;k++) { + if (nodes[k].token == T_SYMBOL&&LookupVariable(&nodes[k]) == i) nodes[k].value.intData=j; } FindVarUsage(nodes, usage, vars->numVariables); break; @@ -634,19 +648,19 @@ static void VariableReuse(NodeList* _nodes, VariableList* vars, int numArgs, Var static void DeadVariableRemoval(NodeList* _nodes, VariableList* vars, int numArgs) { int i, var, j; - Node* nodes=_nodes->nodes; - int *uses=(int*)calloc(1, vars->numVariables*4); - for(i=0;inumVariables;i++) uses[i]=0; - for(i=0;i<_nodes->numNodes;i++) { - if(nodes[i].token==T_SYMBOL && (var=LookupVariable(&nodes[i]))!=-1) uses[var]++; + Node* nodes = _nodes->nodes; + int *uses = (int*)calloc(1, vars->numVariables * 4); + for (i = 0; i < vars->numVariables; i++) uses[i] = 0; + for (i = 0; i < _nodes->numNodes; i++) { + if (nodes[i].token == T_SYMBOL && (var = LookupVariable(&nodes[i])) != -1) uses[var]++; } - for(i=vars->numVariables-1;i>=0;i--) { - if(!uses[i]) { - memmove(&vars->variables[i], &vars->variables[i+1], (vars->numVariables-(i+1))*sizeof(Variable)); + for (i = vars->numVariables - 1; i >= 0;i--) { + if (!uses[i]) { + memmove(&vars->variables[i], &vars->variables[i + 1], (vars->numVariables - (i + 1)) * sizeof(Variable)); vars->numVariables--; parseMessageAtNode(&nodes[0], "Eliminating variable id %d", i); - for(j=0;j<_nodes->numNodes;j++) { - if(nodes[j].token==T_SYMBOL&&LookupVariable(&nodes[j])>i) nodes[j].value.intData--; + for (j = 0; j < _nodes->numNodes; j++) { + if (nodes[j].token == T_SYMBOL && LookupVariable(&nodes[j]) > i) nodes[j].value.intData--; } } } @@ -654,80 +668,80 @@ static void DeadVariableRemoval(NodeList* _nodes, VariableList* vars, int numArg } static int Combine(NodeList* _nodes) { - int i, depth, j, k, matched=0; + int i, depth, j, k, matched = 0; char op; - Node* nodes=_nodes->nodes; - for(i=5;i<_nodes->numNodes-4;i++) { - if(nodes[i].tokenT_ASSIGN_DIV) continue; - switch(nodes[i].token) { - case T_ASSIGN_ADD: op='+'; break; - case T_ASSIGN_SUB: op='-'; break; - case T_ASSIGN_MUL: op='*'; break; - case T_ASSIGN_DIV: op='/'; break; + Node* nodes = _nodes->nodes; + for (i = 5; i < _nodes->numNodes - 4; i++) { + if (nodes[i].token < T_ASSIGN_ADD || nodes[i].token > T_ASSIGN_DIV) continue; + switch (nodes[i].token) { + case T_ASSIGN_ADD: op = '+'; break; + case T_ASSIGN_SUB: op = '-'; break; + case T_ASSIGN_MUL: op = '*'; break; + case T_ASSIGN_DIV: op = '/'; break; } - assert(nodes[i+1].token==T_START_EXPRESSION); - assert(nodes[i-2].token==T_START_STATEMENT); - assert(nodes[i-1].token==T_SYMBOL); - if(nodes[i-3].token!=T_END_STATEMENT) continue; - depth=1; - j=i-3; - while(depth) { + assert(nodes[i + 1].token == T_START_EXPRESSION); + assert(nodes[i - 2].token == T_START_STATEMENT); + assert(nodes[i - 1].token == T_SYMBOL); + if (nodes[i - 3].token != T_END_STATEMENT) continue; + depth = 1; + j = i - 3; + while (depth) { j--; - if(nodes[j].token==T_START_STATEMENT) depth--; - else if(nodes[j].token==T_END_STATEMENT) depth++; + if (nodes[j].token == T_START_STATEMENT) depth--; + else if (nodes[j].token == T_END_STATEMENT) depth++; } - assert(nodes[j].token==T_START_STATEMENT); - if(nodes[j+1].token!=T_SYMBOL||nodes[j+2].token!=T_ASSIGN||nodes[j+1].value.intData!=nodes[i-1].value.intData||nodes[j+1].value.type!=nodes[i-1].value.type) continue; + assert(nodes[j].token == T_START_STATEMENT); + if (nodes[j + 1].token != T_SYMBOL || nodes[j + 2].token != T_ASSIGN || nodes[j + 1].value.intData != nodes[i - 1].value.intData || nodes[j + 1].value.type != nodes[i - 1].value.type) continue; parseMessageAtNode(&nodes[i], "Combining assignments"); - matched=1; + matched = 1; - assert(nodes[i-4].token==T_END_EXPRESSION); - depth=1; - k=i+1; - while(depth) { + assert(nodes[i - 4].token == T_END_EXPRESSION); + depth = 1; + k = i + 1; + while (depth) { k++; - if(nodes[k].token==T_START_EXPRESSION) depth++; - else if(nodes[k].token==T_END_EXPRESSION) depth--; + if (nodes[k].token == T_START_EXPRESSION) depth++; + else if (nodes[k].token == T_END_EXPRESSION) depth--; } - assert(nodes[k].token==T_END_EXPRESSION); - assert(nodes[k+1].token==T_END_STATEMENT); - memmove(&nodes[i-4], &nodes[i+2], (k-i-1)*sizeof(Node)); - assert(nodes[k-6].token==T_END_EXPRESSION); - nodes[k-6].token=op; - nodes[k-5].token=T_END_EXPRESSION; - nodes[k-4].token=T_END_STATEMENT; - memmove(&nodes[k-3], &nodes[k+2], (_nodes->numNodes-k-2)*sizeof(Node)); - _nodes->numNodes-=6; + assert(nodes[k].token == T_END_EXPRESSION); + assert(nodes[k + 1].token == T_END_STATEMENT); + memmove(&nodes[i - 4], &nodes[i + 2], (k - i - 1) * sizeof(Node)); + assert(nodes[k - 6].token == T_END_EXPRESSION); + nodes[k - 6].token = op; + nodes[k - 5].token = T_END_EXPRESSION; + nodes[k - 4].token = T_END_STATEMENT; + memmove(&nodes[k - 3], &nodes[k + 2], (_nodes->numNodes - k - 2) * sizeof(Node)); + _nodes->numNodes -= 6; } return matched; } static void OptimizeProcedure(Procedure* proc) { int found; - int hasVars=proc->variables.variables!=0; + int hasVars = proc->variables.variables != 0; Value *values; VarUsage *usage; - if(hasVars) { - values = (Value*)malloc(sizeof(Value)*proc->variables.numVariables); - usage=(VarUsage*)malloc(proc->variables.numVariables*sizeof(VarUsage)); + if (hasVars) { + values = (Value*)malloc(sizeof(Value) * proc->variables.numVariables); + usage = (VarUsage*)malloc(proc->variables.numVariables * sizeof(VarUsage)); } do { - found=0; - found=ConstantFolding(&proc->nodes); - if(hasVars) { - if (optimize>=3) { // constant propagation is known to break code - found|=ConstantPropagation(&proc->nodes, proc->variables.variables, values, proc->variables.numVariables, proc->numArgs); + found = 0; + found = ConstantFolding(&proc->nodes); + if (hasVars) { + if (optimize >= 3) { // constant propagation is known to break code + found |= ConstantPropagation(&proc->nodes, proc->variables.variables, values, proc->variables.numVariables, proc->numArgs); } - found|=DeadStoreRemoval(&proc->nodes, &proc->variables, usage); + found |= DeadStoreRemoval(&proc->nodes, &proc->variables, usage); } - found|=DeadCodeRemoval(&proc->nodes); - found|=Combine(&proc->nodes); - } while(found); - if(hasVars) { + found |= DeadCodeRemoval(&proc->nodes); + found |= Combine(&proc->nodes); + } while (found); + if (hasVars) { DeadVariableRemoval(&proc->nodes, &proc->variables, proc->numArgs); //use this twice so that VariableReuse has no completely dead variables to worry about - if (optimize>=3) { // variable reuse is known to break code + if (optimize >= 3) { // variable reuse is known to break code VariableReuse(&proc->nodes, &proc->variables, proc->numArgs, usage); DeadVariableRemoval(&proc->nodes, &proc->variables, proc->numArgs); } @@ -764,8 +778,8 @@ int IsProtectedProc(const char* c) { Protect("combat_is_starting_p_proc"); Protect("combat_is_over_p_proc"); - Protect("node998"); - Protect("node999"); + //Protect("node998"); + //Protect("node999"); return 0; } static int __once = 0; @@ -799,21 +813,21 @@ static void EliminateProcedure(Program *prog, int id) { *namesLen -= remLen; __once = 1; }*/ - memmove(&prog->procedures.procedures[id], &prog->procedures.procedures[id+1], (prog->procedures.numProcedures-(id+1))*sizeof(Procedure)); + memmove(&prog->procedures.procedures[id], &prog->procedures.procedures[id + 1], (prog->procedures.numProcedures - (id + 1)) * sizeof(Procedure)); prog->procedures.numProcedures--; - for(i=1;iprocedures.numProcedures;i++) { - NodeList* list=&prog->procedures.procedures[i].nodes; - for(j=0;jnumNodes;j++) { - if(list->nodes[j].token==T_SYMBOL&&(list->nodes[j].value.type&P_PROCEDURE)&&list->nodes[j].value.intData>=id) { - //assert(list->nodes[j].value.intData!=id); //The procedure elimination can now cope with circular references, which would trigger this assert + for (i = 1; i < prog->procedures.numProcedures; i++) { + NodeList* list = &prog->procedures.procedures[i].nodes; + for (j = 0; j < list->numNodes; j++) { + if (list->nodes[j].token == T_SYMBOL && (list->nodes[j].value.type & P_PROCEDURE) && list->nodes[j].value.intData >= id) { + //assert(list->nodes[j].value.intData != id); //The procedure elimination can now cope with circular references, which would trigger this assert list->nodes[j].value.intData--; } } - if(prog->procedures.procedures[i].type&P_CONDITIONAL) { - list=&prog->procedures.procedures[i].condition; - for(j=0;jnumNodes;j++) { - if(list->nodes[j].token==T_SYMBOL&&(list->nodes[j].value.type&P_PROCEDURE)&&list->nodes[j].value.intData>=id) { - //assert(list->nodes[j].value.intData!=id); + if (prog->procedures.procedures[i].type & P_CONDITIONAL) { + list = &prog->procedures.procedures[i].condition; + for (j = 0; j < list->numNodes; j++) { + if (list->nodes[j].token == T_SYMBOL && (list->nodes[j].value.type & P_PROCEDURE) && list->nodes[j].value.intData >= id) { + //assert(list->nodes[j].value.intData != id); list->nodes[j].value.intData--; } } @@ -823,67 +837,67 @@ static void EliminateProcedure(Program *prog, int id) { //This is the old method of procedure elimination; it wouldn't correctly remove circular references /*static void UpdateProcedureReferences(Procedure* procs, int count) { - int i,j; + int i, j; Node* node; - for(i=1;itoken==T_SYMBOL&&node->value.type==(P_PROCEDURE|P_LOCAL)) procs[node->value.intData].uses++; + for (i = 1; i < count; i++) procs[i].uses = 0; + for (i = 1; i < count; i++) { + for (j = 0; j < procs[i].nodes.numNodes; j++) { + node = &procs[i].nodes.nodes[j]; + if (node->token == T_SYMBOL && node->value.type == (P_PROCEDURE | P_LOCAL)) procs[node->value.intData].uses++; } - if(procs[i].type&P_CONDITIONAL) { - for(j=0;jtoken==T_SYMBOL&&node->value.type==(P_PROCEDURE|P_LOCAL)) procs[node->value.intData].uses++; + if (procs[i].type & P_CONDITIONAL) { + for (j = 0; j < procs[i].condition.numNodes; j++) { + node = &procs[i].condition.nodes[j]; + if (node->token == T_SYMBOL && node->value.type == (P_PROCEDURE | P_LOCAL)) procs[node->value.intData].uses++; } } } } static void DecendUnusedProcedures(Program *prog) { - int i, matched=1; - while(matched) { - matched=0; + int i, matched = 1; + while (matched) { + matched = 0; UpdateProcedureReferences(prog->procedures.procedures, prog->procedures.numProcedures); - for(i=1;iprocedures.numProcedures;i++) { - if(prog->procedures.procedures[i].type&(P_TIMED|P_IMPORT|P_EXPORT|P_CONDITIONAL|P_CRITICAL)) continue; - if(!prog->procedures.procedures[i].uses && !IsProtectedProc(prog->namelist + prog->procedures.procedures[i].name)) { + for (i = 1; i < prog->procedures.numProcedures; i++) { + if (prog->procedures.procedures[i].type & (P_TIMED | P_IMPORT | P_EXPORT | P_CONDITIONAL | P_CRITICAL)) continue; + if (!prog->procedures.procedures[i].uses && !IsProtectedProc(prog->namelist + prog->procedures.procedures[i].name)) { EliminateProcedure(prog, i--); - matched=1; + matched = 1; } } } }*/ static void UpdateProcedureReferences(Procedure* procs, int count) { - int i,j,matched=1; + int i, j, matched = 1; Node* node; - for(i=1;inamelist + procs[i].name) || procs[i].type&(P_TIMED|P_CONDITIONAL|P_EXPORT|P_CRITICAL)) procs[i].uses=1; - //else if(procs[i].type&P_IMPORT) procs[i].uses=2; - else procs[i].uses=0; + for (i = 1; i < count; i++) { + if (IsProtectedProc(currprogram->namelist + procs[i].name) || procs[i].type & (P_TIMED | P_CONDITIONAL | P_EXPORT/* | P_CRITICAL*/)) procs[i].uses = 1; + //else if (procs[i].type & P_IMPORT) procs[i].uses = 2; + else procs[i].uses = 0; } - while(matched) { - matched=0; - for(i=1;itoken==T_SYMBOL&&node->value.type==(P_PROCEDURE|P_LOCAL)) { - if(!procs[node->value.intData].uses) { - matched=1; - procs[node->value.intData].uses=1; + while (matched) { + matched = 0; + for (i = 1; i < count; i++) { + if (procs[i].uses != 1 || procs[i].type & P_IMPORT) continue; + procs[i].uses = 2; + for (j = 0; j < procs[i].nodes.numNodes; j++) { + node = &procs[i].nodes.nodes[j]; + if (node->token == T_SYMBOL && node->value.type == (P_PROCEDURE | P_LOCAL)) { + if (!procs[node->value.intData].uses) { + matched = 1; + procs[node->value.intData].uses = 1; } } } - if(procs[i].type&P_CONDITIONAL) { - for(j=0;jtoken==T_SYMBOL&&node->value.type==(P_PROCEDURE|P_LOCAL)) { - if(!procs[node->value.intData].uses) { - matched=1; - procs[node->value.intData].uses=1; + if (procs[i].type & P_CONDITIONAL) { + for (j = 0; j < procs[i].condition.numNodes; j++) { + node = &procs[i].condition.nodes[j]; + if (node->token == T_SYMBOL && node->value.type == (P_PROCEDURE | P_LOCAL)) { + if (!procs[node->value.intData].uses) { + matched = 1; + procs[node->value.intData].uses = 1; } } } @@ -895,40 +909,40 @@ static void UpdateProcedureReferences(Procedure* procs, int count) { static void DecendUnusedProcedures(Program *prog) { int i; UpdateProcedureReferences(prog->procedures.procedures, prog->procedures.numProcedures); - for(i=1;iprocedures.numProcedures;i++) { - if(!prog->procedures.procedures[i].uses) EliminateProcedure(prog, i--); + for (i = 1; i < prog->procedures.numProcedures; i++) { + if (!prog->procedures.procedures[i].uses) EliminateProcedure(prog, i--); } } static int ConstantPropagateGlobals(Program *prog) { - Value* values=(Value*)malloc(prog->variables.numVariables*sizeof(Variable)); - int i, j, matched=0; + Value* values = (Value*)malloc(prog->variables.numVariables * sizeof(Variable)); + int i, j, matched = 0; //Make initial list of variables - for(i=0;ivariables.numVariables;i++) { + for (i = 0; i < prog->variables.numVariables; i++) { values[i]=prog->variables.variables[i].value; } //Check for any that are assigned - for(i=1;iprocedures.numProcedures;i++) { - for(j=1;jprocedures.procedures[i].nodes.numNodes;j++) { - if(prog->procedures.procedures[i].nodes.nodes[j].token>=T_ASSIGN&&prog->procedures.procedures[i].nodes.nodes[j].token<=T_ASSIGN_DIV) { - Node* node=&prog->procedures.procedures[i].nodes.nodes[j-1]; - assert(node->token==T_SYMBOL); - if(node->value.type==P_GLOBAL) values[node->value.intData].type=-1; + for (i = 1; i < prog->procedures.numProcedures; i++) { + for (j = 1; j < prog->procedures.procedures[i].nodes.numNodes; j++) { + if (prog->procedures.procedures[i].nodes.nodes[j].token >= T_ASSIGN && prog->procedures.procedures[i].nodes.nodes[j].token <= T_ASSIGN_DIV) { + Node* node = &prog->procedures.procedures[i].nodes.nodes[j - 1]; + assert(node->token == T_SYMBOL); + if (node->value.type == P_GLOBAL) values[node->value.intData].type = -1; } } } //Constant propagate any that are not - for(i=1;iprocedures.numProcedures;i++) { - for(j=1;jprocedures.procedures[i].nodes.numNodes;j++) { - Node* node=&prog->procedures.procedures[i].nodes.nodes[j]; - if(node->token==T_SYMBOL && node->value.type==P_GLOBAL && values[node->value.intData].type!=-1) { - if(node[1].token==T_START_EVENT) { + for (i = 1; i < prog->procedures.numProcedures; i++) { + for (j = 1; j < prog->procedures.procedures[i].nodes.numNodes; j++) { + Node* node = &prog->procedures.procedures[i].nodes.nodes[j]; + if (node->token == T_SYMBOL && node->value.type == P_GLOBAL && values[node->value.intData].type != -1) { + if (node[1].token == T_START_EVENT) { parseWarningAtNode(node, "Global variable '%s' is called as a procedure butnever recieves a value", prog->namelist + prog->variables.variables[node->value.intData].name); } else { parseMessageAtNode(node, "Constant propagating global variable %s", prog->namelist + prog->variables.variables[node->value.intData].name); - node->token=T_CONSTANT; - node->value=values[node->value.intData]; - matched=1; + node->token = T_CONSTANT; + node->value = values[node->value.intData]; + matched = 1; } } } @@ -938,20 +952,20 @@ static int ConstantPropagateGlobals(Program *prog) { } static void ShiftSymbolIntValues(Program *prog, int var, int matchType) { - int i,j; - for(i=1;iprocedures.numProcedures;i++) { - NodeList* list=&prog->procedures.procedures[i].nodes; - for(j=0;jnumNodes;j++) { - if(list->nodes[j].token==T_SYMBOL&&list->nodes[j].value.type==matchType&&list->nodes[j].value.intData>=var) { - assert(list->nodes[j].value.intData!=var); + int i, j; + for (i = 1; i < prog->procedures.numProcedures; i++) { + NodeList* list = &prog->procedures.procedures[i].nodes; + for (j = 0; j < list->numNodes; j++) { + if (list->nodes[j].token == T_SYMBOL && list->nodes[j].value.type == matchType && list->nodes[j].value.intData >= var) { + assert(list->nodes[j].value.intData != var); list->nodes[j].value.intData--; } } - if(prog->procedures.procedures[i].type&P_CONDITIONAL) { - list=&prog->procedures.procedures[i].condition; - for(j=0;jnumNodes;j++) { - if(list->nodes[j].token==T_SYMBOL&&list->nodes[j].value.type==matchType&&list->nodes[j].value.intData>=var) { - assert(list->nodes[j].value.intData!=var); + if (prog->procedures.procedures[i].type & P_CONDITIONAL) { + list = &prog->procedures.procedures[i].condition; + for (j = 0; j < list->numNodes; j++) { + if (list->nodes[j].token == T_SYMBOL && list->nodes[j].value.type == matchType && list->nodes[j].value.intData >= var) { + assert(list->nodes[j].value.intData != var); list->nodes[j].value.intData--; } } @@ -960,46 +974,46 @@ static void ShiftSymbolIntValues(Program *prog, int var, int matchType) { } static void EliminateUnreferencedGlobals(Program *prog) { - int i,j,var; + int i, j, var; Node* node; //count variable references - for(i=0;ivariables.numVariables;i++) prog->variables.variables[i].uses=0; - for(i=0;iexternals.numVariables;i++) - prog->externals.variables[i].uses=(prog->externals.variables[i].type == V_EXPORT); // assume export variable is always used - for(i=1;iprocedures.numProcedures;i++) { - for(j=0;jprocedures.procedures[i].nodes.numNodes;j++) { - node=&prog->procedures.procedures[i].nodes.nodes[j]; - if(node->token==T_SYMBOL) { - if(node->value.type==P_GLOBAL) prog->variables.variables[node->value.intData].uses++; - if(node->value.type==P_EXTERN) prog->externals.variables[node->value.intData].uses++; + for (i = 0; i < prog->variables.numVariables; i++) prog->variables.variables[i].uses = 0; + for (i = 0; i < prog->externals.numVariables; i++) + prog->externals.variables[i].uses = (prog->externals.variables[i].type == V_EXPORT); // assume export variable is always used + for (i = 1; i < prog->procedures.numProcedures; i++) { + for (j = 0; j < prog->procedures.procedures[i].nodes.numNodes; j++) { + node = &prog->procedures.procedures[i].nodes.nodes[j]; + if (node->token == T_SYMBOL) { + if (node->value.type == P_GLOBAL) prog->variables.variables[node->value.intData].uses++; + if (node->value.type == P_EXTERN) prog->externals.variables[node->value.intData].uses++; } } - if(prog->procedures.procedures[i].type&P_CONDITIONAL) { - for(j=0;jprocedures.procedures[i].condition.numNodes;j++) { - node=&prog->procedures.procedures[i].condition.nodes[j]; - if(node->token==T_SYMBOL) { - if(node->value.type==P_GLOBAL) prog->variables.variables[node->value.intData].uses++; - if(node->value.type==P_EXTERN) prog->externals.variables[node->value.intData].uses++; + if (prog->procedures.procedures[i].type & P_CONDITIONAL) { + for (j = 0; j < prog->procedures.procedures[i].condition.numNodes; j++) { + node = &prog->procedures.procedures[i].condition.nodes[j]; + if (node->token == T_SYMBOL) { + if (node->value.type == P_GLOBAL) prog->variables.variables[node->value.intData].uses++; + if (node->value.type == P_EXTERN) prog->externals.variables[node->value.intData].uses++; } } } } //remove any variables that aren't referenced or exported - for(var=prog->variables.numVariables-1;var>=0;var--) { - if(!prog->variables.variables[var].uses) { + for (var = prog->variables.numVariables - 1; var >= 0; var--) { + if (!prog->variables.variables[var].uses) { parseMessageAtNode(0, "Eliminating unused global variable %s", prog->namelist + prog->variables.variables[var].name); - memmove(&prog->variables.variables[var], &prog->variables.variables[var+1], (prog->variables.numVariables-(var+1))*sizeof(Variable)); + memmove(&prog->variables.variables[var], &prog->variables.variables[var + 1], (prog->variables.numVariables - (var + 1)) * sizeof(Variable)); prog->variables.numVariables--; ShiftSymbolIntValues(prog, var, P_GLOBAL); } } // remove unreferenced import variables - for(var=prog->externals.numVariables-1;var>=0;var--) { - if(!prog->externals.variables[var].uses) { + for (var = prog->externals.numVariables - 1; var >= 0; var--) { + if (!prog->externals.variables[var].uses) { parseMessageAtNode(0, "Eliminating unused import variable %s", prog->namelist + prog->externals.variables[var].name); - memmove(&prog->externals.variables[var], &prog->externals.variables[var+1], (prog->externals.numVariables-(var+1))*sizeof(Variable)); + memmove(&prog->externals.variables[var], &prog->externals.variables[var + 1], (prog->externals.numVariables - (var + 1)) * sizeof(Variable)); prog->externals.numVariables--; ShiftSymbolIntValues(prog, var, P_EXTERN); } @@ -1007,90 +1021,90 @@ static void EliminateUnreferencedGlobals(Program *prog) { } static void CompressNamelist(Program *prog) { - char* list=prog->namelist + 4, *endptr; - int entries=0, *refs, *offsets, *transforms, i, j; + char* list = prog->namelist + 4, *endptr; + int entries = 0, *refs, *offsets, *transforms, i, j; Procedure* proc; - while(*(unsigned short*)list != 0xffff) { + while (*(unsigned short*)list != 0xffff) { entries++; - list+=*(unsigned short*)list + 2; + list += *(unsigned short*)list + 2; } - endptr=list + 2; - refs=(int*)calloc(1, entries*4); - offsets=(int*)malloc(entries*4); - transforms=(int*)malloc(entries*4); + endptr = list + 2; + refs = (int*)calloc(1, entries * 4); + offsets = (int*)malloc(entries * 4); + transforms = (int*)malloc(entries * 4); //first find the offsets - list=prog->namelist +4; - for(i=0;inamelist; - list+=*(unsigned short*)list + 2; + list = prog->namelist +4; + for (i = 0; i < entries; i++) { + offsets[i] = 2 + (unsigned int)list - (unsigned int)prog->namelist; + list += *(unsigned short*)list + 2; } - memcpy(transforms, offsets, entries*4); + memcpy(transforms, offsets, entries * 4); //Then check all variables, imports and procedures to see where in the namelist they point - for(i=0;iexternals.numVariables;i++) { - for(j=0;jexternals.variables[i].name==offsets[j]) refs[j]|=1; + for (i = 0; i < prog->externals.numVariables; i++) { + for (j = 0; j < entries; j++) { + if (prog->externals.variables[i].name == offsets[j]) refs[j] |= 1; } } - for(i=0;ivariables.numVariables;i++) { - for(j=0;jvariables.variables[i].name==offsets[j]) refs[j]|=2; + for (i = 0; i < prog->variables.numVariables; i++) { + for (j = 0; j < entries; j++) { + if (prog->variables.variables[i].name == offsets[j]) refs[j] |= 2; } } - for(i=0;iprocedures.numProcedures;i++) { + for (i = 0; i < prog->procedures.numProcedures; i++) { proc = &prog->procedures.procedures[i]; - for(j=0;jname==offsets[j]) refs[j]|=4; + for (j = 0; j < entries; j++) { + if (proc->name == offsets[j]) refs[j] |= 4; } } //For each string that isn't referenced, remove it - for(i=entries-1;i>=0;i--) { - if(!refs[i]) { - int len=*(unsigned short*)(prog->namelist + offsets[i] - 2) + 2; + for (i = entries - 1; i >= 0; i--) { + if (!refs[i]) { + int len = *(unsigned short*)(prog->namelist + offsets[i] - 2) + 2; parseMessageAtNode(0, "Removing unused string '%s' from program namespace", prog->namelist + offsets[i]); - (*(unsigned int*)prog->namelist)-=len; + (*(unsigned int*)prog->namelist) -= len; memmove(prog->namelist + offsets[i] - 2, len + prog->namelist + offsets[i] - 2, endptr - (len + prog->namelist + offsets[i] - 2)); - transforms[i]=0x7fffffff; - for(j=i+1;j=3) { + transforms[i] = 0x7fffffff; + for (j = i + 1; j < entries; j++) transforms[j] -= len; + } else if (refs[i] == 2&&optimize>=3) { int len=*(unsigned short*)(prog->namelist + offsets[i] - 2) + 2; - if(len>4) { + if (len > 4) { parseMessageAtNode(0, "Shortening non-visible string '%s' in program namespace", prog->namelist + offsets[i]); - *(unsigned short*)(prog->namelist + offsets[i] - 2)=2; - *(char*)(prog->namelist + offsets[i] + 0)='a'; - *(char*)(prog->namelist + offsets[i] + 1)=0; - (*(unsigned int*)prog->namelist)-=len-4; + *(unsigned short*)(prog->namelist + offsets[i] - 2) = 2; + *(char*)(prog->namelist + offsets[i] + 0) = 'a'; + *(char*)(prog->namelist + offsets[i] + 1) = 0; + (*(unsigned int*)prog->namelist) -= len - 4; memmove(prog->namelist + offsets[i] + 2, len + prog->namelist + offsets[i] - 2, endptr - (len + prog->namelist + offsets[i] - 2)); - for(j=i+1;jexternals.numVariables;i++) { - for(j=0;jexternals.variables[i].name==offsets[j]) { - assert(transforms[j]!=0x7fffffff); - prog->externals.variables[i].name=transforms[j]; + for (i = 0; i < prog->externals.numVariables; i++) { + for (j = 0; j < entries; j++) { + if (prog->externals.variables[i].name == offsets[j]) { + assert(transforms[j] != 0x7fffffff); + prog->externals.variables[i].name = transforms[j]; break; } } } - for(i=0;ivariables.numVariables;i++) { - for(j=0;jvariables.variables[i].name==offsets[j]) { - assert(transforms[j]!=0x7fffffff); - prog->variables.variables[i].name=transforms[j]; + for (i = 0; i < prog->variables.numVariables; i++) { + for (j = 0; j < entries; j++) { + if (prog->variables.variables[i].name == offsets[j]) { + assert(transforms[j] != 0x7fffffff); + prog->variables.variables[i].name = transforms[j]; break; } } } - for(i=0;iprocedures.numProcedures;i++) { + for (i = 0; i < prog->procedures.numProcedures; i++) { proc = &prog->procedures.procedures[i]; - for(j=0;jname==offsets[j]) { - assert(transforms[j]!=0x7fffffff); - proc->name=transforms[j]; + for (j = 0; j < entries; j++) { + if (proc->name == offsets[j]) { + assert(transforms[j] != 0x7fffffff); + proc->name = transforms[j]; break; } } @@ -1102,27 +1116,26 @@ static void CompressNamelist(Program *prog) { } void optimizeTree(Program *prog) { - int i, matched=1; - currprogram=prog; - if(optimize==1) + int i, matched = 1; + currprogram = prog; + if (optimize == 1) { DecendUnusedProcedures(prog); EliminateUnreferencedGlobals(prog); } else { - while(matched) { - matched=0; + while (matched) { + matched = 0; DecendUnusedProcedures(prog); - for(i=1;iprocedures.numProcedures;i++) { - if(prog->procedures.procedures[i].type&P_IMPORT) continue; + for (i = 1; i procedures.numProcedures; i++) { + if (prog->procedures.procedures[i].type & P_IMPORT) continue; OptimizeProcedure(&prog->procedures.procedures[i]); } DecendUnusedProcedures(prog); - matched|=ConstantPropagateGlobals(prog); + matched |= ConstantPropagateGlobals(prog); EliminateUnreferencedGlobals(prog); } } CompressNamelist(prog); } - diff --git a/sslc.vcxproj b/sslc.vcxproj index 059e740..483ce99 100644 --- a/sslc.vcxproj +++ b/sslc.vcxproj @@ -124,7 +124,7 @@ Disabled WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true + false EnableFastChecks MultiThreadedDebugDLL @@ -145,10 +145,6 @@ - - - - @@ -191,7 +187,7 @@ Full true - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;WIN2K;%(PreprocessorDefinitions) MultiThreaded