1061da546Spatrick //===- LLDBOptionDefEmitter.cpp -------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick //
9061da546Spatrick // These tablegen backends emits LLDB's OptionDefinition values for different
10061da546Spatrick // LLDB commands.
11061da546Spatrick //
12061da546Spatrick //===----------------------------------------------------------------------===//
13061da546Spatrick
14061da546Spatrick #include "LLDBTableGenBackends.h"
15061da546Spatrick #include "LLDBTableGenUtils.h"
16061da546Spatrick #include "llvm/ADT/StringExtras.h"
17061da546Spatrick #include "llvm/TableGen/Record.h"
18061da546Spatrick #include "llvm/TableGen/StringMatcher.h"
19061da546Spatrick #include "llvm/TableGen/TableGenBackend.h"
20061da546Spatrick #include <vector>
21061da546Spatrick
22061da546Spatrick using namespace llvm;
23061da546Spatrick using namespace lldb_private;
24061da546Spatrick
25061da546Spatrick namespace {
26061da546Spatrick struct CommandOption {
27061da546Spatrick std::vector<std::string> GroupsArg;
28061da546Spatrick bool Required = false;
29061da546Spatrick std::string FullName;
30061da546Spatrick std::string ShortName;
31061da546Spatrick std::string ArgType;
32061da546Spatrick bool OptionalArg = false;
33061da546Spatrick std::string Validator;
34061da546Spatrick std::vector<StringRef> Completions;
35061da546Spatrick std::string Description;
36061da546Spatrick
37061da546Spatrick CommandOption() = default;
CommandOption__anon57766ab50111::CommandOption38061da546Spatrick CommandOption(Record *Option) {
39061da546Spatrick if (Option->getValue("Groups")) {
40061da546Spatrick // The user specified a list of groups.
41061da546Spatrick auto Groups = Option->getValueAsListOfInts("Groups");
42061da546Spatrick for (int Group : Groups)
43061da546Spatrick GroupsArg.push_back("LLDB_OPT_SET_" + std::to_string(Group));
44061da546Spatrick } else if (Option->getValue("GroupStart")) {
45061da546Spatrick // The user specified a range of groups (with potentially only one
46061da546Spatrick // element).
47061da546Spatrick int GroupStart = Option->getValueAsInt("GroupStart");
48061da546Spatrick int GroupEnd = Option->getValueAsInt("GroupEnd");
49061da546Spatrick for (int i = GroupStart; i <= GroupEnd; ++i)
50061da546Spatrick GroupsArg.push_back("LLDB_OPT_SET_" + std::to_string(i));
51061da546Spatrick }
52061da546Spatrick
53061da546Spatrick // Check if this option is required.
54061da546Spatrick Required = Option->getValue("Required");
55061da546Spatrick
56061da546Spatrick // Add the full and short name for this option.
57dda28197Spatrick FullName = std::string(Option->getValueAsString("FullName"));
58dda28197Spatrick ShortName = std::string(Option->getValueAsString("ShortName"));
59061da546Spatrick
60061da546Spatrick if (auto A = Option->getValue("ArgType"))
61061da546Spatrick ArgType = A->getValue()->getAsUnquotedString();
62061da546Spatrick OptionalArg = Option->getValue("OptionalArg") != nullptr;
63061da546Spatrick
64061da546Spatrick if (Option->getValue("Validator"))
65dda28197Spatrick Validator = std::string(Option->getValueAsString("Validator"));
66061da546Spatrick
67061da546Spatrick if (Option->getValue("Completions"))
68061da546Spatrick Completions = Option->getValueAsListOfStrings("Completions");
69061da546Spatrick
70061da546Spatrick if (auto D = Option->getValue("Description"))
71061da546Spatrick Description = D->getValue()->getAsUnquotedString();
72061da546Spatrick }
73061da546Spatrick };
74061da546Spatrick } // namespace
75061da546Spatrick
emitOption(const CommandOption & O,raw_ostream & OS)76061da546Spatrick static void emitOption(const CommandOption &O, raw_ostream &OS) {
77061da546Spatrick OS << " {";
78061da546Spatrick
79061da546Spatrick // If we have any groups, we merge them. Otherwise we move this option into
80061da546Spatrick // the all group.
81061da546Spatrick if (O.GroupsArg.empty())
82061da546Spatrick OS << "LLDB_OPT_SET_ALL";
83061da546Spatrick else
84061da546Spatrick OS << llvm::join(O.GroupsArg.begin(), O.GroupsArg.end(), " | ");
85061da546Spatrick
86061da546Spatrick OS << ", ";
87061da546Spatrick
88061da546Spatrick // Check if this option is required.
89061da546Spatrick OS << (O.Required ? "true" : "false");
90061da546Spatrick
91061da546Spatrick // Add the full and short name for this option.
92061da546Spatrick OS << ", \"" << O.FullName << "\", ";
93061da546Spatrick OS << '\'' << O.ShortName << "'";
94061da546Spatrick
95061da546Spatrick // Decide if we have either an option, required or no argument for this
96061da546Spatrick // option.
97061da546Spatrick OS << ", OptionParser::";
98061da546Spatrick if (!O.ArgType.empty()) {
99061da546Spatrick if (O.OptionalArg)
100061da546Spatrick OS << "eOptionalArgument";
101061da546Spatrick else
102061da546Spatrick OS << "eRequiredArgument";
103061da546Spatrick } else
104061da546Spatrick OS << "eNoArgument";
105061da546Spatrick OS << ", ";
106061da546Spatrick
107061da546Spatrick if (!O.Validator.empty())
108061da546Spatrick OS << O.Validator;
109061da546Spatrick else
110061da546Spatrick OS << "nullptr";
111061da546Spatrick OS << ", ";
112061da546Spatrick
113*f6aab3d8Srobert if (!O.ArgType.empty())
114*f6aab3d8Srobert OS << "g_argument_table[eArgType" << O.ArgType << "].enum_values";
115061da546Spatrick else
116061da546Spatrick OS << "{}";
117061da546Spatrick OS << ", ";
118061da546Spatrick
119061da546Spatrick // Read the tab completions we offer for this option (if there are any)
120061da546Spatrick if (!O.Completions.empty()) {
121061da546Spatrick std::vector<std::string> CompletionArgs;
122061da546Spatrick for (llvm::StringRef Completion : O.Completions)
123061da546Spatrick CompletionArgs.push_back("CommandCompletions::e" + Completion.str() +
124061da546Spatrick "Completion");
125061da546Spatrick
126061da546Spatrick OS << llvm::join(CompletionArgs.begin(), CompletionArgs.end(), " | ");
127061da546Spatrick } else
128061da546Spatrick OS << "CommandCompletions::eNoCompletion";
129061da546Spatrick
130061da546Spatrick // Add the argument type.
131061da546Spatrick OS << ", eArgType";
132061da546Spatrick if (!O.ArgType.empty()) {
133061da546Spatrick OS << O.ArgType;
134061da546Spatrick } else
135061da546Spatrick OS << "None";
136061da546Spatrick OS << ", ";
137061da546Spatrick
138061da546Spatrick // Add the description if there is any.
139061da546Spatrick if (!O.Description.empty()) {
140061da546Spatrick OS << "\"";
141061da546Spatrick llvm::printEscapedString(O.Description, OS);
142061da546Spatrick OS << "\"";
143061da546Spatrick } else
144061da546Spatrick OS << "\"\"";
145061da546Spatrick OS << "},\n";
146061da546Spatrick }
147061da546Spatrick
148061da546Spatrick /// Emits all option initializers to the raw_ostream.
emitOptions(std::string Command,std::vector<Record * > Records,raw_ostream & OS)149061da546Spatrick static void emitOptions(std::string Command, std::vector<Record *> Records,
150061da546Spatrick raw_ostream &OS) {
151061da546Spatrick std::vector<CommandOption> Options;
152061da546Spatrick for (Record *R : Records)
153061da546Spatrick Options.emplace_back(R);
154061da546Spatrick
155061da546Spatrick std::string ID = Command;
156061da546Spatrick std::replace(ID.begin(), ID.end(), ' ', '_');
157061da546Spatrick // Generate the macro that the user needs to define before including the
158061da546Spatrick // *.inc file.
159061da546Spatrick std::string NeededMacro = "LLDB_OPTIONS_" + ID;
160061da546Spatrick
161061da546Spatrick // All options are in one file, so we need put them behind macros and ask the
162061da546Spatrick // user to define the macro for the options that are needed.
163061da546Spatrick OS << "// Options for " << Command << "\n";
164061da546Spatrick OS << "#ifdef " << NeededMacro << "\n";
165061da546Spatrick OS << "constexpr static OptionDefinition g_" + ID + "_options[] = {\n";
166061da546Spatrick for (CommandOption &CO : Options)
167061da546Spatrick emitOption(CO, OS);
168061da546Spatrick // We undefine the macro for the user like Clang's include files are doing it.
169061da546Spatrick OS << "};\n";
170061da546Spatrick OS << "#undef " << NeededMacro << "\n";
171061da546Spatrick OS << "#endif // " << Command << " command\n\n";
172061da546Spatrick }
173061da546Spatrick
EmitOptionDefs(RecordKeeper & Records,raw_ostream & OS)174061da546Spatrick void lldb_private::EmitOptionDefs(RecordKeeper &Records, raw_ostream &OS) {
175061da546Spatrick emitSourceFileHeader("Options for LLDB command line commands.", OS);
176061da546Spatrick
177061da546Spatrick std::vector<Record *> Options = Records.getAllDerivedDefinitions("Option");
178061da546Spatrick for (auto &CommandRecordPair : getRecordsByName(Options, "Command")) {
179061da546Spatrick emitOptions(CommandRecordPair.first, CommandRecordPair.second, OS);
180061da546Spatrick }
181061da546Spatrick }
182