#define _LARGEFILE64_SOURCE 1 #define _LARGEFILE_SOURCE 1 #include #include #include #include #include #include #include #include #include "AST.h" #include "code-call.h" #include "code-foreach.h" #include "code-ipanal.h" #include "code.h" #include "compiler.h" #include "decls.h" #include "errors.h" #include "optimize.h" #include "optimize-monitors.h" #include "parse.h" #include "postpone.h" #include "sharing.h" #include "streq.h" #include "stats.h" #include "tclimits.h" #include "templates/instantiate.h" #include "utils.h" #include "inline.h" #include "typecheck.h" #include "stoptifu/parameter.h" // NOTE: IF YOU ADD NEW COMMAND-LINE FLAGS TO TC, PLEASE UPDATE ./notes/tcflags.txt int DEBUG = 0; bool alias_anal = false; bool compilerLocComments = true; bool debug_opt = false; bool debug_commonsub; bool debug_defs = false; bool tallyCalls = false; int compile_verbose_level = 0; bool output_info = false; bool preprocess_only = false; string cpp_defines = ""; // Optimization is on by default. int base_opt_level = 1; bool opt_osr = true; bool opt_uae = true; bool opt_deadvar = true; bool opt_unreachable = true; bool opt_sr = true; bool opt_lift = true; bool opt_usi = true; bool opt_copy = true; bool opt_subexpr = false; bool opt_foldextra = true; int opt_for_to_foreach_level = 2; int opt_inline_level = 1; int opt_inline_maxdepth = DEFAULT_MAX_INLINING_DEPTH; bool opt_DME = false; bool opt_local = true; bool opt_sharing = true; // default: do not use stoptifu (temporary?) bool opt_stoptifu = false; // No Stoptifu stats unless requested. int stat_stoptifu_level = 0; // default to safe behavior bool megatile_verification = false; // default to asking lots of questions bool opt_stoptifu_greenlight = false; // default to regular tiles, not doubled in each dimension bool opt_stoptifu_force_big = false; bool opt_storage_schedule_read, opt_storage_read_from_reg, opt_storage_usib, opt_storage_ts, opt_stoptifu_fusion; #ifndef STOPTIFU_MAYBE #define STOPTIFU_NO 0 #define STOPTIFU_MAYBE 11 #define STOPTIFU_YES 22 #endif int opt_coarse_interleaving = STOPTIFU_MAYBE, opt_allow_any_shape = STOPTIFU_MAYBE; /* Negative value means get a value from the parameter file. */ int opt_stoptifu_min_domain_size = -1; /* Negative value means get a value from the parameter file. */ int opt_stoptifu_rr_aggressiveness = -1; /* Use new (more conservative, faster) dominator analysis. */ bool opt_use_new_dom = true; /* By default, ignore the "parallel" marker on foreach loops. */ bool ignore_parallel = true; bool test_sr = false; bool fixAliasing = false; bool codeGen_libs = true; bool infer_nooverlap = false; bool codeGen_main = true; string *mainclass = NULL; bool use_sglobal_inference = true; bool use_goto = false; bool use_nonTrivialSizeCheck = false; bool bounds_checking = true; bool force_java = false, force_ti = false; bool freeMethodBodies = true; extern bool sizeofRuntimeIntIs64; extern bool sizeofRuntimeCharIs32; extern bool sizeofRuntimeShortIs32; extern int max_errors; bool parse_only = false; string codeGen_outdir = "./tc-gen/"; // default to something other than CWD to prevent accidents int debugger_level = 0; bool line_directives = false; char *dump_ast, *dump_phase; bool sequential_consistency = false; string tcCompilerFlags; string tlib_include_dir; set suppressed_warnings; void show_rusage(); void OutOfMemHandler() { // print an error message using a minimal amount of memory static char msg[] = "Out of memory.\n"; write(2, msg, sizeof(msg)-1); fputs("tc has run out of memory.\n", stderr); fputs("we recommend allocating more swap space or turning off some optimizations.\n", stderr); fflush(stderr); show_rusage(); exit(-1); // don't dump a huge core - probably just exacerbate the problem return; } void useTcbuildMsg() { cerr << "This is tc, the internal Titanium translator." << endl; cerr << "You should use the tcbuild compiler driver for building all Titanium programs." << endl; cerr << "See 'tcbuild --help-tcflags' for documentation on tc flags." << endl; exit(-1); } void ti_setenv(string key, string value) { string *s = new string(key); s->append("="); s->append(value); if (putenv((char*)s->c_str())) perror("putenv"); // do NOT free s - putenv needs it assert(getenv(key.c_str()) && !strcmp(getenv(key.c_str()), value.c_str())); } void initSigHandlers(); void maxrlimit(); void outputSettingsInfo(int showargs); int main(int argc, char* argv[]) { set_new_handler(&OutOfMemHandler); //set_malloc_handler(&OutOfMemHandler); //while (1) new char[1024]; //while (1) malloc(1024); initSigHandlers(); //*((char*)NULL) = 0; maxrlimit(); if (argc < 2) useTcbuildMsg(); bool frontend_only = false; int args_terminated = 0; bool got_magic_flag = false; parameter_parse_args(argc, argv); // record compiler flags tcCompilerFlags = ""; for (int i=0; i < argc; i++) tcCompilerFlags += string(i>0?" ":"") + string(argv[i]); opt_storage_schedule_read = opt_storage_read_from_reg = opt_storage_usib = opt_storage_ts = opt_stoptifu_fusion = opt_stoptifu; while (argc > 1 && argv[1][0] == '-' && !args_terminated) { if (streq(argv[1], "-tcbuild")) { got_magic_flag = true; argc--; argv++; } else if (streq(argv[1], "-fonly")) { frontend_only = true; got_magic_flag = true; argc--; argv++; } else if (streq(argv[1], "-parse")) { parse_only = true; got_magic_flag = true; argc--; argv++; } else if (streq(argv[1], "-info")) { output_info = true; argc--; argv++; } else if (!strncmp(argv[1],"-classlib=",10)) { ti_setenv("CLASSLIB", strchr(argv[1],'=')+1); argc--; argv++; } else if (streq(argv[1], "-g0")) { debugger_level = 0; line_directives = false; argc--; argv++; } else if ((streq(argv[1], "-g")) || (streq(argv[1], "-g1"))) { debugger_level = 1; line_directives = true; argc--; argv++; } else if (streq(argv[1], "-E")) { preprocess_only = true; argc--; argv++; } else if (!strncmp(argv[1],"-D",2) || !strncmp(argv[1],"-U",2)) { string newdef = argv[1]; if (argv[1][2] == '\0' && argc > 2) { // -D FOO=BAR or -U FOO newdef += argv[2]; argc--; argv++; } argc--; argv++; for (string::size_type i = newdef.find("\'"); i != newdef.npos; i = newdef.find("\'",i+1)) { newdef.replace(i,1,"\'\"\'\"\'"); i += 4; } cpp_defines += string(" \'") + newdef + "\'"; } else if (streq(argv[1], "-nocolumn")) { error_column = false; argc--; argv++; } else if (streq(argv[1], "-line")) { error_column = true; argc--; argv++; } else if (streq(argv[1], "-noline")) { line_directives = false; argc--; argv++; } else if (streq(argv[1], "-line")) { line_directives = true; argc--; argv++; } else if (streq(argv[1], "-debug")) { DEBUG = 1; argc--; argv++; } else if (!strncmp(argv[1], "-verbose",8)) { compile_verbose_level = 1; if (argv[1][8]) compile_verbose_level = atoi(argv[1]+8); argc--; argv++; } else if (streq(argv[1], "-sizeof")) { argc--; argv++; if (argc > 1) { if (streq(argv[1], "jint=64")) { sizeofRuntimeIntIs64 = true; argc--; argv++; } else if (streq(argv[1], "jint=32")) { sizeofRuntimeIntIs64 = false; argc--; argv++; } else if (streq(argv[1], "jchar=32")) { sizeofRuntimeCharIs32 = true; argc--; argv++; } else if (streq(argv[1], "jchar=16")) { sizeofRuntimeCharIs32 = false; argc--; argv++; } else if (streq(argv[1], "jshort=32")) { sizeofRuntimeShortIs32 = true; argc--; argv++; } else if (streq(argv[1], "jshort=16")) { sizeofRuntimeShortIs32 = false; argc--; argv++; } } } else if (streq(argv[1], "-trivialSizeCheck")) { use_nonTrivialSizeCheck = true; argc--; argv++; } else if (streq(argv[1], "-notrivialSizeCheck")) { use_nonTrivialSizeCheck = false; argc--; argv++; } else if (streq(argv[1], "-goto")) { use_goto = true; argc--; argv++; } else if (streq(argv[1], "-nogoto")) { use_goto = false; argc--; argv++; } else if (streq(argv[1], "-bc")) { bounds_checking = true; argc--; argv++; } else if (streq(argv[1], "-nobc")) { bounds_checking = false; argc--; argv++; } else if (streq(argv[1], "-debugopt")) { debug_opt = true; argc--; argv++; } else if (streq(argv[1], "-debugdefs")) { debug_defs = true; argc--; argv++; } else if (streq(argv[1], "-srtest")) { test_sr = true; argc--; argv++; } else if (streq(argv[1], "-stats")) { stat_foreach = true; argc--; argv++; } else if (streq(argv[1], "-callstats")) { tallyCalls = true; argc--; argv++; } else if (streq(argv[1], "-Stoptifustats") || streq(argv[1], "-Stoptifustats1")) { stat_stoptifu_level = 1; argc--; argv++; } else if (streq(argv[1], "-Stoptifustats2")) { stat_stoptifu_level = 2; argc--; argv++; } else if (streq(argv[1], "-fixsharing")) { fixAliasing = true; argc--; argv++; } else if (streq(argv[1], "-parallelize")) { ignore_parallel = false; argc--; argv++; } else if (streq(argv[1], "-max-errors")) { char *end = 0; int value = strtol( argv[2], &end, 0 ); if (*end) cerr << "Ignoring garbled max-errors: " << argv[2] << endl; else max_errors = value; argc -= 2; argv += 2; } else if (streq(argv[1], "-noparallelize")) { ignore_parallel = true; argc--; argv++; } else if (streq(argv[1], "-O0")) { base_opt_level = 0; opt_uae = false; opt_deadvar = false; opt_unreachable = false; opt_lift = false; opt_sr = false; opt_osr = false; opt_usi = false; opt_storage_schedule_read = opt_storage_read_from_reg = opt_storage_usib = opt_stoptifu_fusion = opt_storage_ts = opt_stoptifu = false; opt_inline_level = 0; opt_for_to_foreach_level = 0; opt_local = false; opt_sharing = false; opt_monitors = false; opt_copy = false; opt_foldextra = false; opt_subexpr = false; argc--; argv++; } else if (streq(argv[1], "-O") || streq(argv[1], "-O1")) { base_opt_level = 1; opt_uae = true; opt_deadvar = true; opt_unreachable = true; opt_lift = true; opt_sr = true; opt_osr = true; opt_usi = true; /* opt_storage_schedule_read = opt_storage_read_from_reg = opt_storage_usib = opt_stoptifu_fusion = opt_storage_ts = opt_stoptifu = true; */ opt_inline_level = 1; opt_for_to_foreach_level = 2; opt_local = true; opt_sharing = true; //opt_monitors = true; // DOB: off by default because it's unsafe //opt_DME = true; // DOB: off by default because it's unsafe opt_copy = true; opt_foldextra = true; //opt_subexpr = true; // off by default for now - still under development argc--; argv++; } else if (streq(argv[1], "-OSR")) { opt_sr = true; argc--; argv++; } else if (streq(argv[1], "-OnoSR")) { opt_sr = false; argc--; argv++; } else if (streq(argv[1], "-OOSR")) { opt_osr = true; argc--; argv++; } else if (streq(argv[1], "-OnoOSR")) { opt_osr = false; argc--; argv++; } else if (streq(argv[1], "-OUSI")) { opt_usi = true; argc--; argv++; } else if (streq(argv[1], "-OnoUSI")) { opt_usi = false; argc--; argv++; } else if (streq(argv[1], "-OStoptifu")) { opt_storage_schedule_read = opt_storage_read_from_reg = opt_storage_usib = opt_stoptifu_fusion = opt_storage_ts = opt_stoptifu = true; argc--; argv++; } else if (streq(argv[1], "-OnoStoptifu")) { opt_storage_schedule_read = opt_storage_read_from_reg = opt_storage_usib = opt_stoptifu_fusion = opt_storage_ts = opt_stoptifu = false; argc--; argv++; } else if (streq(argv[1], "-OStoptifu-greenlight")) { opt_stoptifu_greenlight = opt_stoptifu = true; argc--; argv++; } else if (streq(argv[1], "-OnoStoptifu-greenlight")) { opt_stoptifu_greenlight = false; argc--; argv++; } else if (streq(argv[1], "-OStoptifu-force-big")) { opt_stoptifu_force_big = opt_stoptifu = true; argc--; argv++; } else if (streq(argv[1], "-OnoStoptifu-force-big")) { opt_stoptifu_force_big = false; argc--; argv++; } else if (streq(argv[1], "-OStoptifu-min-size")) { char *end = 0; int value = strtol( argv[2], &end, 0 ); if (*end) cerr << "Discarding garbled Stoptifu min size: " << argv[2] << endl; else if (value < 0) cerr << "Ignoring negative Stoptifu min size: " << argv[2] << endl; else opt_stoptifu_min_domain_size = value; argc -= 2; argv += 2; } else if (streq(argv[1], "-OmaybeStoptifu-min-size")) { opt_stoptifu_min_domain_size = -1; argc--; argv++; } else if (streq(argv[1], "-OStoptifu-aa")) { opt_stoptifu = true; opt_allow_any_shape = STOPTIFU_YES; argc--; argv++; } else if (streq(argv[1], "-OmaybeStoptifu-aa")) { opt_stoptifu = true; opt_allow_any_shape = STOPTIFU_MAYBE; argc--; argv++; } else if (streq(argv[1], "-OnoStoptifu-aa")) { opt_allow_any_shape = STOPTIFU_NO; argc--; argv++; } else if (streq(argv[1], "-OStoptifu-ci")) { opt_stoptifu = true; opt_coarse_interleaving = STOPTIFU_YES; argc--; argv++; } else if (streq(argv[1], "-OmaybeStoptifu-ci")) { opt_stoptifu = true; opt_coarse_interleaving = STOPTIFU_MAYBE; argc--; argv++; } else if (streq(argv[1], "-OnoStoptifu-ci")) { opt_coarse_interleaving = STOPTIFU_NO; argc--; argv++; } #if 0 else if (streq(argv[1], "-OStoptifu-sr")) { opt_storage_schedule_read = opt_stoptifu = true; argc--; argv++; } else if (streq(argv[1], "-OnoStoptifu-sr")) { opt_storage_schedule_read = false; argc--; argv++; } #endif else if (streq(argv[1], "-OStoptifu-rr")) { char *end = 0; int value = strtol( argv[2], &end, 0 ); if (*end) cerr << "Discarding garbled Stoptifu read reg aggressiveness: " << argv[2] << endl; else if (value < 0) cerr << "Ignoring negative Stoptifu read reg aggressiveness: " << argv[2] << endl; else opt_stoptifu_rr_aggressiveness = value; argc -= 2; argv += 2; } else if (streq(argv[1], "-OmaybeStoptifu-rr")) { opt_stoptifu_rr_aggressiveness = -1; argc--; argv++; } else if (streq(argv[1], "-OStoptifu-usib")) { opt_storage_usib = opt_stoptifu = true; argc--; argv++; } else if (streq(argv[1], "-OnoStoptifu-usib")) { opt_storage_usib = false; argc--; argv++; } else if (streq(argv[1], "-OStoptifu-fu")) { opt_stoptifu_fusion = opt_stoptifu = true; argc--; argv++; } else if (streq(argv[1], "-OnoStoptifu-fu")) { opt_stoptifu_fusion = false; argc--; argv++; } else if (streq(argv[1], "-OStoptifu-ts")) { opt_storage_ts = opt_stoptifu = true; argc--; argv++; } else if (streq(argv[1], "-OnoStoptifu-ts")) { opt_storage_ts = false; argc--; argv++; } else if (streq(argv[1], "-OStoptifu-mv")) { megatile_verification = true; argc--; argv++; } else if (streq(argv[1], "-OnoStoptifu-mv")) { megatile_verification = false; argc--; argv++; } else if (streq(argv[1], "-OUAE")) { opt_uae = true; argc--; argv++; } else if (streq(argv[1], "-OnoUAE")) { opt_uae = false; argc--; argv++; } else if (streq(argv[1], "-Odeadvar")) { opt_deadvar = true; argc--; argv++; } else if (streq(argv[1], "-Onodeadvar")) { opt_deadvar = false; argc--; argv++; } else if (streq(argv[1], "-Ounreachable")) { opt_unreachable = true; argc--; argv++; } else if (streq(argv[1], "-Onounreachable")) { opt_unreachable = false; argc--; argv++; } else if (streq(argv[1], "-Olift")) { opt_lift = true; argc--; argv++; } else if (streq(argv[1], "-Onolift")) { opt_lift = false; argc--; argv++; } else if (streq(argv[1], "-Onoinline")) { opt_inline_level = 0; argc--; argv++; } else if (streq(argv[1], "-Oinline1")) { opt_inline_level = 1; argc--; argv++; } else if (streq(argv[1], "-Oinline2")) { opt_inline_level = 2; argc--; argv++; } else if (streq(argv[1], "-Oinline-maxdepth")) { char *end = 0; int value = strtol( argv[2], &end, 0 ); if (*end) cerr << "Ignoring garbled inlining max depth: " << argv[2] << endl; else opt_inline_maxdepth = value; argc -= 2; argv += 2; } else if (streq(argv[1], "-ODME")) { opt_DME = true; argc--; argv++; } else if (streq(argv[1], "-Onofor")) { opt_for_to_foreach_level = 0; argc--; argv++; } else if (streq(argv[1], "-Ofor1")) { opt_for_to_foreach_level = 1; argc--; argv++; } else if (streq(argv[1], "-Ofor2")) { opt_for_to_foreach_level = 2; argc--; argv++; } else if (streq(argv[1], "-Ofinalize")) { opt_finalize = true; argc--; argv++; } else if (streq(argv[1], "-Onofinalize")) { opt_finalize = false; argc--; argv++; } else if (streq(argv[1], "-Olocal")) { opt_local = true; argc--; argv++; } else if (streq(argv[1], "-Onolocal")) { opt_local = false; argc--; argv++; } else if (streq(argv[1], "-Ofoldextra")) { opt_foldextra = true; argc--; argv++; } else if (streq(argv[1], "-Onofoldextra")) { opt_foldextra = false; argc--; argv++; } else if (streq(argv[1], "-Ocopy")) { opt_copy = true; argc--; argv++; } else if (streq(argv[1], "-Onocopy")) { opt_copy = false; argc--; argv++; } else if (streq(argv[1], "-Osubexpr")) { opt_subexpr = true; argc--; argv++; } else if (streq(argv[1], "-Onosubexpr")) { opt_subexpr = false; argc--; argv++; } else if (streq(argv[1], "-Onew-dom")) { opt_use_new_dom = true; argc--; argv++; } else if (streq(argv[1], "-Ononew-dom")) { opt_use_new_dom = false; argc--; argv++; } else if (streq(argv[1], "-debug-qual")) { debug_qual = true; argc--; argv++; } #ifdef USE_SGLOBAL_INFERENCE else if (streq(argv[1], "-infer-sglobal")) { use_sglobal_inference = true; argc--; argv++; } #endif // USE_SGLOBAL_INFERENCE else if (streq(argv[1], "-noinfer-sglobal")) { use_sglobal_inference = false; argc--; argv++; } else if (streq(argv[1], "-Osharing")) { opt_sharing = true; argc--; argv++; } else if (streq(argv[1], "-Onosharing")) { opt_sharing = false; argc--; argv++; } else if (streq(argv[1], "-Omonitors")) { opt_monitors = true; argc--; argv++; } else if (streq(argv[1], "-Onomonitors")) { opt_monitors = false; argc--; argv++; } else if (streq(argv[1], "-stats-monitors")) { stat_monitors = true; argc--; argv++; } else if (streq(argv[1], "-sharing-early")) { sharingEnforcement = Early; argc--; argv++; } else if (streq(argv[1], "-sharing-late")) { sharingEnforcement = Late; argc--; argv++; } else if (streq(argv[1], "-infer-nooverlap")){ infer_nooverlap = true; argc--; argv++; } else if (streq(argv[1], "-nolibs")) { codeGen_libs = false; argc--; argv++; } else if (streq(argv[1], "-libs")) { codeGen_libs = true; argc--; argv++; } else if (streq(argv[1], "-nomain")) { codeGen_main = false; argc--; argv++; } else if (streq(argv[1], "-main")) { codeGen_main = true; argc--; argv++; } else if (streq(argv[1], "-mainclass")) { mainclass = new string(argv[2]); argc -= 2; argv += 2; } else if (streq(argv[1], "-outdir")) { codeGen_outdir = argv[2]; codeGen_outdir += '/'; argc -= 2; argv += 2; } else if (streq(argv[1], "-tlib-include-dir")) { tlib_include_dir = argv[2]; tlib_include_dir += '/'; argc -= 2; argv += 2; } else if (streq(argv[1], "-dumpast")) { dump_ast = argv[2]; argc -= 2; argv += 2; } else if (streq(argv[1], "-dumpphase")) { dump_phase = argv[2]; if (dump_ast == NULL) dump_ast = "all"; argc -= 2; argv += 2; } else if (streq(argv[1], "-woff") || streq(argv[1], "-won")) { char *tmp = new char[strlen(argv[2])+2]; char *p = tmp, *q; strcpy(tmp, argv[2]); strcat(tmp,","); while (*p && (q = strpbrk(p,":,"))) { *q = '\0'; if (streq(argv[1], "-woff")) suppressed_warnings.insert(string(p)); else suppressed_warnings.erase(string(p)); p = q + 1; } delete tmp; argc -= 2; argv += 2; } else if (streq(argv[1], "-java")) { force_java = true; argc--; argv++; } else if (streq(argv[1], "-ti")) { force_ti = true; argc--; argv++; } else if (streq(argv[1], "-AA")) { alias_anal = true; argc--; argv++; } else if (streq(argv[1], "-noAA")) { alias_anal = false; argc--; argv++; } else if (streq(argv[1], "--")) { args_terminated = 1; argc--; argv++; } else if (streq(argv[1], "-inheritance-depth")) { char *end = 0; int value = strtol( argv[2], &end, 0 ); if (*end) cerr << "Ignoring garbled inheritance depth: " << argv[2] << endl; else maxInheritanceDepth = value; argc -= 2; argv += 2; } else if (streq(argv[1], "-template-instantiations")) { char *end = 0; int value = strtol( argv[2], &end, 0 ); if (*end) cerr << "Ignoring garbled template instantiations: " << argv[2] << endl; else maxTemplateInstantiations = value; argc -= 2; argv += 2; } else if (streq(argv[1], "-template-depth")) { char *end = 0; int value = strtol( argv[2], &end, 0 ); if (*end) cerr << "Ignoring garbled template depth: " << argv[2] << endl; else maxTemplateDepth = value; argc -= 2; argv += 2; } else if (streq(argv[1], "-debug-instantiation")) { debug_instantiation = true; argc--; argv++; } else if (streq(argv[1], "-debug-postpone")) { debug_postpone = true; argc--; argv++; } else if (streq(argv[1], "-free-methods")) { freeMethodBodies = true; argc--; argv++; } else if (streq(argv[1], "-no-free-methods")) { freeMethodBodies = false; argc--; argv++; } #ifdef USE_TC_GC else if (streq(argv[1], "-no-gc")) { GC_dont_gc = 1; argc--; argv++; } else if (streq(argv[1], "-gc-find-leaks")) { GC_find_leak = 1; argc--; argv++; } #endif // garbage collection in tc else if (streq(argv[1], "-sequential-consistency")) { sequential_consistency = true; argc--; argv++; } else { cerr << "Ignoring unknown option: " << argv[1] << '\n'; argc--; argv++; } } if (output_info) { outputSettingsInfo(0); exit(0); } if (!got_magic_flag) useTcbuildMsg(); struct stat sbuf; if (stat(codeGen_outdir.c_str(), &sbuf) && errno == ENOENT) { if (mkdir(codeGen_outdir.c_str(), (unsigned int)-1)) { fprintf(stderr,"mkdir(%s) for -outdir failed: %s\n",codeGen_outdir.c_str(), strerror(errno)); exit(-1); } } if (stat(codeGen_outdir.c_str(), &sbuf)) { fprintf(stderr,"Bad -outdir %s: %s\n",codeGen_outdir.c_str(), strerror(errno)); exit(-1); } else if (!S_ISDIR(sbuf.st_mode)) { fprintf(stderr,"-outdir %s is not a directory!\n",codeGen_outdir.c_str()); exit(-1); } // check that CLASSLIB looks valid string classlib; char *p = getenv("CLASSLIB"); int numdirs = 0; while ( p && *p ) { char tmp[255]; char *q = strchr(p,':'); if (!q) q = p+strlen(p); strncpy(tmp,p,q-p); tmp[q-p] = '\0'; if (strlen(tmp)) { struct stat sbuf; if ((stat(tmp, &sbuf) && errno == ENOENT) || (!stat(tmp, &sbuf) && !S_ISDIR(sbuf.st_mode))) { Warning() << "ignoring non-existent CLASSLIB directory '" << tmp << "'" << endl; } else { if (numdirs) classlib.append(":"); classlib.append(tmp); numdirs++; } } if (*q) p = q+1; else break; } if (!numdirs) { Error() << "CLASSLIB is empty!" << endl; exit(1); } ti_setenv("CLASSLIB", classlib); // If testing strength reduction, make sure we do that optimization. if (test_sr) opt_sr = true; // If SR is on, we must do lifting so that arrays used in the SR // calculations are available in the loop header. if (opt_sr && !opt_lift) { opt_lift = true; cout << "Note: lifting must be on if strength reduction is on." " -Olift assumed." << endl; } if (opt_stoptifu) { if (!opt_sr) cout << "Note: use of Stoptifu with strength reduction disabled" " is unlikely to be useful." << endl; opt_storage_read_from_reg = opt_stoptifu && (opt_stoptifu_rr_aggressiveness != 0); } debug_commonsub = false; // debug_commonsub = debug_opt; if (preprocess_only) compile_verbose_level = 0; if (argc > 2 && preprocess_only) { cerr << "Error: Specified -E and more than one source file" << endl; exit(-1); } compile_status(1,"initTheSystem()..."); initTheSystem(); compile_status(1,"Parsing source files..."); if (argc > 1) for (int source = 1; source < argc; ++source) load(argv[source], !force_java, false); //!force_java && (force_ti || isTitanium(argv[source]))); else load("", stdin, !force_java, false); if (mainclass && mainclass->find(".") != string::npos) { // ensure -main classname is loaded TreeNode *name = TreeNode::omitted; string tmp = *mainclass; while (1) { string::size_type pos = tmp.find("."); name = new NameNode(name, intern(tmp.substr(0,pos)), NULL); if (pos == string::npos) break; tmp = tmp.substr(pos+1); } llist *empty = NULL; CompileUnitNode *cun = new CompileUnitNode(new string(""), TreeNode::omitted, //new NameNode(new NameNode(TreeNode::omitted, intern("ti"),NULL), // intern("internal"), NULL)/* ti.internal package */, cons((TreeNode*)new ImportNode(name)), new TreeListNode(empty), NULL); cun->packageResolution(); cun->loaded(false); } if (!parse_only) { staticSemantics(); if (!frontend_only && NumErrors() == 0) { optimizeMonitors(); /* Interprocedural analyses (currently only AA). */ if (alias_anal) { /* Set up all basic blocks first. */ setupBblocks(); IPAnal(); } /* Interprocedural opts can go here. */ if (opt_inline_level) { compile_status(1,"Method inlining..."); doMethodInlining(); } /* Mark method bodies etc. for optimization. */ lazyOptimize(); /* Generate code, doing some optimization as we go. */ backend(); } } compile_status(1, string("tc exiting ") + ( (NumErrors() > 0) ? string("(failed with ") + int2string(NumErrors()) + " errors)" : string("(success)"))); if (compile_verbose_level >= 1) show_rusage(); exit(NumErrors() > 0 ? 1 : 0); } void publishCompileSettings(ClassDecl *CompileSettingsDecl) { TreeNode *cdn = CompileSettingsDecl->source(); foriter (tf, cdn->members()->allChildren(), TreeNode::ChildIter) { TreeNode *f = *tf; if (isFieldDeclNode(f)) { assert(f->flags() & Common::Public); assert(f->flags() & Common::Static); assert(f->flags() & Common::Final); if (*f->simpName()->ident() == "optimize") f->initExpr(new PrimitiveLitNode(Literal((bool)base_opt_level > 0))); else if (*f->simpName()->ident() == "debug") f->initExpr(new PrimitiveLitNode(Literal((bool)debugger_level > 0))); else if (*f->simpName()->ident() == "bcheck") f->initExpr(new PrimitiveLitNode(Literal((bool)bounds_checking))); else f->error() << "unknown CompileSettings field"; } } } /* attempt to maximize allowable cpu and memory resource limits for this process, ignoring any errors */ void maxrlimit() { int debug = 0; #ifdef __USE_GNU /* workaround a glibc header bug */ #define RLIM_T __rlimit_resource_t #else #define RLIM_T int #endif struct res_s { RLIM_T res; const char *desc; } res[] = { #ifdef RLIMIT_CPU { RLIMIT_CPU, "RLIMIT_CPU" }, #endif #ifdef RLIMIT_DATA { RLIMIT_DATA, "RLIMIT_DATA" }, #endif #ifdef RLIMIT_RSS { RLIMIT_RSS, "RLIMIT_RSS" }, #endif #ifdef RLIMIT_STACK { RLIMIT_STACK, "RLIMIT_STACK" }, #endif #ifdef RLIMIT_AS { RLIMIT_AS, "RLIMIT_AS" }, #endif }; #define SET_RLIMITS(structname, getrlimit, setrlimit) do { \ structname rval; size_t idx; \ for (idx = 0; idx < sizeof(res)/sizeof(struct res_s); idx++) { \ if (!getrlimit(res[idx].res, &rval)) { \ if (debug > 1) printf("%s == { %i, %i }\n", res[idx].desc, \ (int)rval.rlim_cur, (int)rval.rlim_max); \ if (rval.rlim_cur == RLIM_INFINITY || \ rval.rlim_max == RLIM_INFINITY) rval.rlim_cur = RLIM_INFINITY; \ else rval.rlim_cur = rval.rlim_max; \ if (debug > 1) { \ if (rval.rlim_cur == RLIM_INFINITY) \ printf("setting %s to RLIM_INFINITY\n", res[idx].desc); \ else printf("setting %s to %i\n", res[idx].desc, (int)rval.rlim_cur); \ } \ if (setrlimit(res[idx].res, &rval) && debug) perror("setrlimit"); \ } else if (debug) perror("getrlimit"); \ } \ } while (0) #if defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) SET_RLIMITS(struct rlimit, getrlimit, setrlimit); #endif /* do 64-bit second, to favor the potentially higher limits */ #if defined(HAVE_GETRLIMIT64) && defined(HAVE_SETRLIMIT64) SET_RLIMITS(struct rlimit64, getrlimit64, setrlimit64); #endif } void show_rusage() { struct rusage ru; if (getrusage(RUSAGE_SELF, &ru)) { perror("failed to getrusage"); return; } cout << "tc time: total: " << compile_time() << " user: " << compile_time(&(ru.ru_utime)) << " system: " << compile_time(&(ru.ru_stime)) << endl; #ifdef HAVE_GETRUSAGE_PAGE cout << " Page reclaims: " << ru.ru_minflt << " Page faults: " << ru.ru_majflt << " Process swaps: " << ru.ru_nswap << endl; #endif #ifdef __linux__ { FILE *fp = fopen("/proc/self/status","r"); if (!fp) perror("fopen(/proc/self/status)"); else { cout << " Memory:" << endl; char buf[1024]; while (fgets(buf, 1024, fp)) { if (!strncmp(buf, "Vm", 2)) cout << " " << buf; } fclose(fp); } } #else /* following stupidly unimplemented in Linux */ #ifdef HAVE_GETRUSAGE_MAXRSS cout << " Max resident set size: " << ru.ru_maxrss << " KB" << endl; #endif #ifdef HAVE_GETRUSAGE_MEM double exetime = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec + 0.000001 * (ru.ru_utime.tv_usec + ru.ru_stime.tv_usec); cout << " Ave Memory Usage: " << " shared: " << (int)( ru.ru_ixrss / exetime ) << " KB" << " data: " << (int)( ru.ru_idrss / exetime ) << " KB" << " stack: " << (int)( ru.ru_isrss / exetime ) << " KB" << endl; #endif #ifdef HAVE_GETRUSAGE_CONTEXT cout << " Context Switches: " << " voluntary: " << ru.ru_nvcsw << " involuntary: " << ru.ru_nivcsw << endl; #endif #endif fflush(NULL); }