// #include "ActiveVars.hpp" // #include "ConstPropagation.hpp" #include "DeadCode.h" #include "Dominators.h" #include "GVN.h" // #include "LoopInvHoist.hpp" // #include "LoopSearch.hpp" #include "ExceptCallMerge.hpp" #include "LoopUnroll.hpp" #include "Mem2Reg.hpp" #include "PassManager.hpp" #include "cminusf_builder.hpp" #include "codegen.hpp" #include "logging.hpp" #include #include #include using namespace std::literals::string_literals; void print_help(std::string exe_name) { std::cout << "Usage: " << exe_name << " [ -h | --help ] [ -o ] [ -emit-llvm ] " "[-mem2reg] [-gvn] [-dump-json] " << std::endl; } int main(int argc, char **argv) { std::string target_path; std::string input_path; bool mem2reg = false; bool gvn = false; bool dump_json = false; bool emit = false; bool assembly = false; bool loopunroll = false; for (int i = 1; i < argc; ++i) { if (argv[i] == "-h"s || argv[i] == "--help"s) { print_help(argv[0]); return 0; } else if (argv[i] == "-o"s || argv[i] == "-S"s) { if (argv[i] == "-S"s) assembly = true; if (target_path.empty() && i + 1 < argc) { target_path = argv[i + 1]; if (target_path.rfind(".") != std::string::npos) target_path = target_path.substr(0, target_path.rfind(".")); i += 1; } else { print_help(argv[0]); return 0; } } else if (argv[i] == "-emit-llvm"s) { emit = true; } else if (argv[i] == "-mem2reg"s) { mem2reg = true; } else if (argv[i] == "-gvn"s) { gvn = true; } else if (argv[i] == "-loopunroll"s) { loopunroll = true; } else if (argv[i] == "-dump-json"s) { dump_json = true; } else { if (input_path.empty()) { input_path = argv[i]; } else { print_help(argv[0]); return 0; } } } if (gvn and not mem2reg) LOG_WARNING << "Enabling GVN without mem2reg"; if (input_path.empty()) { print_help(argv[0]); return 0; } if (target_path.empty()) { auto pos = input_path.rfind('.'); if (pos == std::string::npos) { std::cerr << argv[0] << ": input file " << input_path << " has unknown filetype!" << std::endl; return -1; } else { // if (input_path.substr(pos) != ".cminus") { // std::cerr << argv[0] << ": input file " << input_path << " // has unknown filetype!" << std::endl; return -1; // } target_path = input_path.substr(0, pos); } } auto s = parse(input_path.c_str()); auto a = AST(s); CminusfBuilder builder; try { a.run_visitor(builder); } catch (std::exception e) { std::cout << "Exception catched:\n\t" << e.what() << std::endl; std::cout << "Already generated IR code:\n" << builder.getModule()->print(); return -1; } auto m = builder.getModule(); // m->set_print_name(); PassManager PM(m.get()); if (mem2reg) { PM.add_pass(false); } if (gvn) { PM.add_pass(false); // remove some undef PM.add_pass(false, dump_json); PM.add_pass( false); // delete unused instructions created by GVN } if (loopunroll) { PM.add_pass(false); PM.add_pass(false); } m->set_print_name(); PM.run(); auto IR = m->print(); if (assembly) { CodeGen codegen(m.get()); codegen.run(); std::ofstream target_file(target_path + ".s"); target_file << codegen.print(); target_file.close(); // return 0; } std::ofstream output_stream; auto output_file = target_path + ".ll"; output_stream.open(output_file, std::ios::out); output_stream << "; ModuleID = 'cminus'\n"; output_stream << "source_filename = \"" + input_path + "\"\n\n"; output_stream << IR; output_stream.close(); if (!emit) { std::string lib_path = " -L"s + argv[0]; auto idx = lib_path.rfind('/'); if (idx != std::string::npos) lib_path.erase(lib_path.rfind('/')); else lib_path.clear(); auto cmd_str = "clang -O0 -w -no-pie "s + target_path + ".ll -o " + target_path + lib_path + " -lcminus_io"; int re_code0 = std::system(cmd_str.c_str()); cmd_str = "rm "s + target_path + ".ll"; int re_code1 = std::system(cmd_str.c_str()); if (re_code0 == 0 && re_code1 == 0) return 0; else return 1; } return 0; }