int generate_filter_main(int argc, char **argv, std::ostream &cerr) { const char kUsage[] = "gengen [-g GENERATOR_NAME] [-f FUNCTION_NAME] [-o OUTPUT_DIR] [-r RUNTIME_NAME] [-e EMIT_OPTIONS] " "target=target-string [generator_arg=value [...]]\n\n" " -e A comma separated list of optional files to emit. Accepted values are " "[assembly, bitcode, stmt, html]\n"; std::map<std::string, std::string> flags_info = { { "-f", "" }, { "-g", "" }, { "-o", "" }, { "-e", "" }, { "-r", "" }}; std::map<std::string, std::string> generator_args; for (int i = 1; i < argc; ++i) { if (argv[i][0] != '-') { std::vector<std::string> v = split_string(argv[i], "="); if (v.size() != 2 || v[0].empty() || v[1].empty()) { cerr << kUsage; return 1; } generator_args[v[0]] = v[1]; continue; } auto it = flags_info.find(argv[i]); if (it != flags_info.end()) { if (i + 1 >= argc) { cerr << kUsage; return 1; } it->second = argv[i + 1]; ++i; continue; } cerr << "Unknown flag: " << argv[i] << "\n"; cerr << kUsage; return 1; } std::string runtime_name = flags_info["-r"]; std::vector<std::string> generator_names = GeneratorRegistry::enumerate(); if (generator_names.size() == 0 && runtime_name.empty()) { cerr << "No generators have been registered and not compiling a standalone runtime\n"; cerr << kUsage; return 1; } std::string generator_name = flags_info["-g"]; if (generator_name.empty() && runtime_name.empty()) { // If -g isn't specified, but there's only one generator registered, just use that one. if (generator_names.size() > 1) { cerr << "-g must be specified if multiple generators are registered:\n"; for (auto name : generator_names) { cerr << " " << name << "\n"; } cerr << kUsage; return 1; } generator_name = generator_names[0]; } std::string function_name = flags_info["-f"]; if (function_name.empty()) { // If -f isn't specified, assume function name = generator name. function_name = generator_name; } std::string output_dir = flags_info["-o"]; if (output_dir.empty()) { cerr << "-o must always be specified.\n"; cerr << kUsage; return 1; } if (generator_args.find("target") == generator_args.end()) { cerr << "Target missing\n"; cerr << kUsage; return 1; } GeneratorBase::EmitOptions emit_options; std::vector<std::string> emit_flags = split_string(flags_info["-e"], ","); for (const std::string &opt : emit_flags) { if (opt == "assembly") { emit_options.emit_assembly = true; } else if (opt == "bitcode") { emit_options.emit_bitcode = true; } else if (opt == "stmt") { emit_options.emit_stmt = true; } else if (opt == "html") { emit_options.emit_stmt_html = true; } else if (!opt.empty()) { cerr << "Unrecognized emit option: " << opt << " not one of [assembly, bitcode, stmt, html], ignoring.\n"; } } if (!runtime_name.empty()) { compile_standalone_runtime(output_dir + "/" + runtime_name, parse_target_string(generator_args["target"])); if (generator_name.empty()) { // We're just compiling a runtime return 0; } } std::unique_ptr<GeneratorBase> gen = GeneratorRegistry::create(generator_name, generator_args); if (gen == nullptr) { cerr << "Unknown generator: " << generator_name << "\n"; cerr << kUsage; return 1; } gen->emit_filter(output_dir, function_name, function_name, emit_options); return 0; }
int generate_filter_main(int argc, char **argv, std::ostream &cerr) { const char kUsage[] = "gengen [-g GENERATOR_NAME] [-f FUNCTION_NAME] [-o OUTPUT_DIR] [-r RUNTIME_NAME] [-e EMIT_OPTIONS] [-x EXTENSION_OPTIONS] [-n FILE_BASE_NAME] " "target=target-string [generator_arg=value [...]]\n\n" " -e A comma separated list of files to emit. Accepted values are " "[o, h, assembly, bitcode, stmt, html, cpp]. If omitted, default value is [o, h].\n" " -x A comma separated list of file extension pairs to substitute during file naming, " "in the form [.old=.new[,.old2=.new2]]\n"; std::map<std::string, std::string> flags_info = { { "-f", "" }, { "-g", "" }, { "-o", "" }, { "-e", "" }, { "-n", "" }, { "-x", "" }, { "-r", "" }}; std::map<std::string, std::string> generator_args; for (int i = 1; i < argc; ++i) { if (argv[i][0] != '-') { std::vector<std::string> v = split_string(argv[i], "="); if (v.size() != 2 || v[0].empty() || v[1].empty()) { cerr << kUsage; return 1; } generator_args[v[0]] = v[1]; continue; } auto it = flags_info.find(argv[i]); if (it != flags_info.end()) { if (i + 1 >= argc) { cerr << kUsage; return 1; } it->second = argv[i + 1]; ++i; continue; } cerr << "Unknown flag: " << argv[i] << "\n"; cerr << kUsage; return 1; } std::string runtime_name = flags_info["-r"]; std::vector<std::string> generator_names = GeneratorRegistry::enumerate(); if (generator_names.size() == 0 && runtime_name.empty()) { cerr << "No generators have been registered and not compiling a standalone runtime\n"; cerr << kUsage; return 1; } std::string generator_name = flags_info["-g"]; if (generator_name.empty() && runtime_name.empty()) { // If -g isn't specified, but there's only one generator registered, just use that one. if (generator_names.size() > 1) { cerr << "-g must be specified if multiple generators are registered:\n"; for (auto name : generator_names) { cerr << " " << name << "\n"; } cerr << kUsage; return 1; } generator_name = generator_names[0]; } std::string function_name = flags_info["-f"]; if (function_name.empty()) { // If -f isn't specified, assume function name = generator name. function_name = generator_name; } std::string output_dir = flags_info["-o"]; if (output_dir.empty()) { cerr << "-o must always be specified.\n"; cerr << kUsage; return 1; } if (generator_args.find("target") == generator_args.end()) { cerr << "Target missing\n"; cerr << kUsage; return 1; } // it's OK for file_base_name to be empty: filename will be based on function name std::string file_base_name = flags_info["-n"]; GeneratorBase::EmitOptions emit_options; // Ensure all flags start as false. emit_options.emit_o = emit_options.emit_h = false; std::vector<std::string> emit_flags = split_string(flags_info["-e"], ","); if (emit_flags.empty() || (emit_flags.size() == 1 && emit_flags[0].empty())) { // If omitted or empty, assume .o and .h emit_options.emit_o = emit_options.emit_h = true; } else { // If anything specified, only emit what is enumerated for (const std::string &opt : emit_flags) { if (opt == "assembly") { emit_options.emit_assembly = true; } else if (opt == "bitcode") { emit_options.emit_bitcode = true; } else if (opt == "stmt") { emit_options.emit_stmt = true; } else if (opt == "html") { emit_options.emit_stmt_html = true; } else if (opt == "cpp") { emit_options.emit_cpp = true; } else if (opt == "o") { emit_options.emit_o = true; } else if (opt == "h") { emit_options.emit_h = true; } else if (!opt.empty()) { cerr << "Unrecognized emit option: " << opt << " not one of [assembly, bitcode, stmt, html], ignoring.\n"; } } } auto extension_flags = split_string(flags_info["-x"], ","); for (const std::string &x : extension_flags) { if (x.empty()) { continue; } auto ext_pair = split_string(x, "="); if (ext_pair.size() != 2) { cerr << "Malformed -x option: " << x << "\n"; cerr << kUsage; return 1; } emit_options.extensions[ext_pair[0]] = ext_pair[1]; } const auto target_string = generator_args["target"]; if (!runtime_name.empty()) { compile_standalone_runtime(output_dir + "/" + runtime_name, parse_target_string(target_string)); if (generator_name.empty()) { // We're just compiling a runtime return 0; } } std::unique_ptr<GeneratorBase> gen = GeneratorRegistry::create(generator_name, generator_args); if (gen == nullptr) { cerr << "Unknown generator: " << generator_name << "\n"; cerr << kUsage; return 1; } gen->emit_filter(output_dir, function_name, file_base_name, emit_options); return 0; }