diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-13 13:10:47 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-13 13:10:47 +0800 |
| commit | 444db30751380e8fe459bfeae4c5bb2a93c596eb (patch) | |
| tree | 5c60a23678f836113e75fb2526d3ec7b28b42f55 /backend/utils/TableGen/rcc-tblgen.cpp | |
| parent | fde3e045d4dcc5c404cb4216389e18b0e720b8e0 (diff) | |
| download | rcc-project-444db30751380e8fe459bfeae4c5bb2a93c596eb.tar.gz rcc-project-444db30751380e8fe459bfeae4c5bb2a93c596eb.tar.xz | |
[TableGen] Split the target description generator
Diffstat (limited to 'backend/utils/TableGen/rcc-tblgen.cpp')
| -rw-r--r-- | backend/utils/TableGen/rcc-tblgen.cpp | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/backend/utils/TableGen/rcc-tblgen.cpp b/backend/utils/TableGen/rcc-tblgen.cpp new file mode 100644 index 0000000..3e4e093 --- /dev/null +++ b/backend/utils/TableGen/rcc-tblgen.cpp @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "TableGenBackends.h" +#include "rcc/Support/TextDiagnostic.h" + +#include <filesystem> +#include <fstream> +#include <iostream> +#include <iterator> +#include <string> +#include <string_view> + +namespace { + +struct CommandLine final { + std::string InputPath; + std::string RegisterHeaderPath; + std::string InstructionHeaderPath; + std::string TablesPath; +}; + +[[nodiscard]] bool parseCommandLine(int ArgumentCount, char *Arguments[], CommandLine &Result) { + for (int Index = 1; Index < ArgumentCount; ++Index) { + const std::string_view Argument(Arguments[Index]); + if (Argument == "--input" || Argument == "--register-header" || + Argument == "--instruction-header" || Argument == "--tables") { + if (Index + 1 >= ArgumentCount) { + std::cerr << "rcc-tblgen: missing value for " << Argument << '\n'; + return false; + } + std::string *Destination = nullptr; + if (Argument == "--input") + Destination = &Result.InputPath; + else if (Argument == "--register-header") + Destination = &Result.RegisterHeaderPath; + else if (Argument == "--instruction-header") + Destination = &Result.InstructionHeaderPath; + else + Destination = &Result.TablesPath; + *Destination = Arguments[++Index]; + continue; + } + std::cerr << "rcc-tblgen: unknown argument '" << Argument << "'\n"; + return false; + } + if (!Result.InputPath.empty() && !Result.RegisterHeaderPath.empty() && + !Result.InstructionHeaderPath.empty() && !Result.TablesPath.empty()) { + return true; + } + std::cerr << "usage: rcc-tblgen --input <file> --register-header <file> " + "--instruction-header <file> --tables <file>\n"; + return false; +} + +[[nodiscard]] bool writeFile(const std::filesystem::path &Path, std::string_view Contents) { + std::error_code Error; + std::filesystem::create_directories(Path.parent_path(), Error); + if (Error) { + std::cerr << "rcc-tblgen: cannot create output directory for '" << Path.string() + << "': " << Error.message() << '\n'; + return false; + } + std::ofstream Output(Path, std::ios::binary | std::ios::trunc); + if (!Output) { + std::cerr << "rcc-tblgen: cannot open output '" << Path.string() << "'\n"; + return false; + } + Output.write(Contents.data(), static_cast<std::streamsize>(Contents.size())); + if (Output) { + Output.close(); + return true; + } + std::cerr << "rcc-tblgen: cannot write output '" << Path.string() << "'\n"; + return false; +} + +} // namespace + +int main(int ArgumentCount, char *Arguments[]) { + CommandLine Command; + if (!parseCommandLine(ArgumentCount, Arguments, Command)) + return 1; + + std::ifstream Input(Command.InputPath, std::ios::binary); + if (!Input) { + std::cerr << "rcc-tblgen: cannot open input '" << Command.InputPath << "'\n"; + return 1; + } + const std::string SourceText{std::istreambuf_iterator<char>(Input), + std::istreambuf_iterator<char>()}; + const rcc::targetgen::DescriptionGenerationResult Result = + rcc::targetgen::generateDescription(Command.InputPath, SourceText); + if (!Result.succeeded()) { + const rcc::TextSource Source(Command.InputPath, SourceText); + for (const rcc::TextDiagnostic &Diagnostic : Result.Diagnostics) + std::cerr << rcc::formatTextDiagnostic(Diagnostic, Source) << '\n'; + return 1; + } + + if (!Result.Output) { + std::cerr << "rcc-tblgen: successful generation produced no output\n"; + return 1; + } + const rcc::targetgen::GeneratedDescription &Output = Result.Output.value(); + return writeFile(Command.RegisterHeaderPath, Output.RegisterHeader) && + writeFile(Command.InstructionHeaderPath, Output.InstructionHeader) && + writeFile(Command.TablesPath, Output.TargetTables) + ? 0 + : 1; +} |
