xref: /openbsd-src/gnu/llvm/lldb/utils/TableGen/LLDBOptionDefEmitter.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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