134 lines
3.4 KiB
C++
134 lines
3.4 KiB
C++
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <cstdint>
|
|
#include <getopt.h>
|
|
#include <filesystem>
|
|
|
|
#include "accumulation.h"
|
|
#include "emit.h"
|
|
|
|
/*
|
|
Notes:
|
|
Datapins for same var/symbol are randomized in order of their level, from bottom of nest to top
|
|
Between CUs, types with the same name HAVE TO HAVE the same layout -> randomized together
|
|
*/
|
|
|
|
struct OPTIONS {
|
|
std::string out_file;
|
|
std::string load_targets_file;
|
|
std::string dump_targets_file;
|
|
std::vector<std::string> spslr_files;
|
|
bool no_new_targets = false;
|
|
bool is_module = false;
|
|
};
|
|
|
|
int main(int argc, char** argv) {
|
|
static option long_options[] = {
|
|
{ "help", no_argument, 0, 0 },
|
|
{ "out", required_argument, 0, 0 },
|
|
{ "load-targets", required_argument, 0, 0 },
|
|
{ "dump-targets", required_argument, 0, 0 },
|
|
{ "no-new-targets", no_argument, 0, 0 },
|
|
{ "module", no_argument, 0, 0 },
|
|
{ 0, 0, 0, 0 }
|
|
};
|
|
|
|
OPTIONS opts{};
|
|
int option_index = 0;
|
|
int c;
|
|
|
|
while ((c = getopt_long(argc, argv, "h:o:", long_options, &option_index)) == 0) {
|
|
const option& opt = long_options[option_index];
|
|
std::string optname { opt.name };
|
|
|
|
if (optname == "help") {
|
|
std::cout
|
|
<< "Usage:\n"
|
|
<< " spslr_patchcompile --out=<file> [options] <file>...\n\n"
|
|
<< "Options:\n"
|
|
<< " --read-targets=<file>\n"
|
|
<< " --emit-targets=<file>\n"
|
|
<< " --no-new-targets\n"
|
|
<< " --module\n";
|
|
return 0;
|
|
} else if (optname == "out") {
|
|
opts.out_file = optarg;
|
|
} else if (optname == "load-targets") {
|
|
opts.load_targets_file = optarg;
|
|
} else if (optname == "dump-targets") {
|
|
opts.dump_targets_file = optarg;
|
|
} else if (optname == "no-new-targets") {
|
|
opts.no_new_targets = true;
|
|
} else if (optname == "module") {
|
|
opts.is_module = true;
|
|
} else {
|
|
std::cerr << "Invalid option, try \"--help\"!\n";
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
for (int i = optind; i < argc; ++i)
|
|
opts.spslr_files.emplace_back(argv[i]);
|
|
|
|
if (opts.out_file.empty()) {
|
|
std::cerr << "Missing output file path, supply it via --out=<file>!\n";
|
|
return 1;
|
|
}
|
|
|
|
if (opts.spslr_files.empty()) {
|
|
std::cerr << "Missing spslr files! Pass one or more .spslr metadata files as positional arguments.\n";
|
|
return 1;
|
|
}
|
|
|
|
if (opts.no_new_targets && opts.load_targets_file.empty()) {
|
|
std::cerr << "--no-new-targets requires --load-targets\n";
|
|
return 1;
|
|
}
|
|
|
|
if (!opts.load_targets_file.empty()) {
|
|
if (!load_target_map(opts.load_targets_file)) {
|
|
std::cerr << "Failed to load target map: " << opts.load_targets_file << "\n";
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (!accumulate(opts.spslr_files, opts.no_new_targets)) {
|
|
std::cerr << "Failed to accumulate data from spslr directory!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
std::filesystem::path out_path { opts.out_file };
|
|
if (out_path.has_parent_path()) {
|
|
std::error_code ec;
|
|
std::filesystem::create_directories(out_path.parent_path(), ec);
|
|
if (ec) {
|
|
std::cerr << "failed to create output directory '"
|
|
<< out_path.parent_path().string()
|
|
<< "': " << ec.message() << "\n";
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
std::ofstream out(out_path);
|
|
if (!out) {
|
|
std::cerr << "Failed to open output file!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
if (!emit_patcher_program_asm(out, opts.is_module)) {
|
|
std::cerr << "Failed to write emit patcher program!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
if (!opts.dump_targets_file.empty()) {
|
|
if (!dump_target_map(opts.dump_targets_file)) {
|
|
std::cerr << "Failed to write target map: " << opts.dump_targets_file << "\n";
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|