#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 "config.h" #include "decls.h" #include "errors.h" #include "qual-infer/options.h" #include "qual-infer/local/options.h" #include "qual-infer/sharing/options.h" #include "optimize.h" #include "optimize-monitors.h" #include "parse.h" #include "postpone.h" #include "sharing.h" #include "streq.h" #include "stats.h" #include "templates/depth.h" #include "templates/instantiate.h" #include "utils.h" #include "inline.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; // Optimization is on by default. 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; int opt_for_to_foreach_level = 2; int opt_inline_level = 1; int opt_inline_maxdepth = DEFAULT_MAX_INLINING_DEPTH; bool opt_DME = false; // 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; /* 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 codeGen_main = true; 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; bool parse_only = false; string codeGen_outdir = "./"; int debugger_level = 0; bool line_directives = false; char *dump_ast, *dump_phase; bool sequential_consistency = false; string tcCompilerFlags; void OutOfMemHandler() { // print an error message using a minimal amount of memory static char msg[] = "Out of memory.\n"; write(2, msg, sizeof(msg)); 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); exit(-1); // don't dump a huge core - probably just exacerbate the problem return; } int main(int argc, char* argv[]) { set_new_handler(&OutOfMemHandler); //set_malloc_handler(&OutOfMemHandler); //while (1) new char[1024]; //while (1) malloc(1024); bool frontend_only = false; int args_terminated = 0; 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], "-fonly")) { frontend_only = true; argc--; argv++; } else if (streq(argv[1], "-parse")) { parse_only = true; 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], "-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 (streq(argv[1], "-verbose") || streq(argv[1], "-verbose1")) { compile_verbose_level = 1; argc--; argv++; } else if (streq(argv[1], "-verbose2")) { compile_verbose_level = 2; argc--; argv++; } else if (streq(argv[1], "-verbose3")) { compile_verbose_level = 3; argc--; argv++; } else if (streq(argv[1], "-verbose4")) { compile_verbose_level = 4; 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], "-noparallelize")) { ignore_parallel = true; argc--; argv++; } else if (streq(argv[1], "-O0")) { 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_subexpr = false; argc--; argv++; } else if (streq(argv[1], "-O") || streq(argv[1], "-O1")) { 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_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], "-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], "-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], "-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], "-outdir")) { codeGen_outdir = argv[2]; codeGen_outdir += '/'; 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], "-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], "-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 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; 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); //!force_java && (force_ti || isTitanium(argv[source]))); else load("", stdin, !force_java); 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)"))); exit(NumErrors() > 0 ? 1 : 0); }