Ejemplo n.º 1
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] "
                          "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;
}
Ejemplo n.º 2
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;
}