1 //===- LLDBOptionDefEmitter.cpp -------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // These tablegen backends emits LLDB's OptionDefinition values for different
12 //===----------------------------------------------------------------------===//
14 #include "LLDBTableGenBackends.h"
15 #include "LLDBTableGenUtils.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/TableGen/Record.h"
18 #include "llvm/TableGen/StringMatcher.h"
19 #include "llvm/TableGen/TableGenBackend.h"
23 using namespace lldb_private
;
26 struct CommandOption
{
27 std::vector
<std::string
> GroupsArg
;
28 bool Required
= false;
30 std::string ShortName
;
32 bool OptionalArg
= false;
33 std::string Validator
;
34 std::vector
<StringRef
> Completions
;
35 std::string Description
;
37 CommandOption() = default;
38 CommandOption(const Record
*Option
) {
39 if (Option
->getValue("Groups")) {
40 // The user specified a list of groups.
41 auto Groups
= Option
->getValueAsListOfInts("Groups");
42 for (int Group
: Groups
)
43 GroupsArg
.push_back("LLDB_OPT_SET_" + std::to_string(Group
));
44 } else if (Option
->getValue("GroupStart")) {
45 // The user specified a range of groups (with potentially only one
47 int GroupStart
= Option
->getValueAsInt("GroupStart");
48 int GroupEnd
= Option
->getValueAsInt("GroupEnd");
49 for (int i
= GroupStart
; i
<= GroupEnd
; ++i
)
50 GroupsArg
.push_back("LLDB_OPT_SET_" + std::to_string(i
));
53 // Check if this option is required.
54 Required
= Option
->getValue("Required");
56 // Add the full and short name for this option.
57 FullName
= std::string(Option
->getValueAsString("FullName"));
58 ShortName
= std::string(Option
->getValueAsString("ShortName"));
60 if (auto A
= Option
->getValue("ArgType"))
61 ArgType
= A
->getValue()->getAsUnquotedString();
62 OptionalArg
= Option
->getValue("OptionalArg") != nullptr;
64 if (Option
->getValue("Validator"))
65 Validator
= std::string(Option
->getValueAsString("Validator"));
67 if (Option
->getValue("Completions"))
68 Completions
= Option
->getValueAsListOfStrings("Completions");
70 if (auto D
= Option
->getValue("Description"))
71 Description
= D
->getValue()->getAsUnquotedString();
76 static void emitOption(const CommandOption
&O
, raw_ostream
&OS
) {
79 // If we have any groups, we merge them. Otherwise we move this option into
81 if (O
.GroupsArg
.empty())
82 OS
<< "LLDB_OPT_SET_ALL";
84 OS
<< llvm::join(O
.GroupsArg
.begin(), O
.GroupsArg
.end(), " | ");
88 // Check if this option is required.
89 OS
<< (O
.Required
? "true" : "false");
91 // Add the full and short name for this option.
92 OS
<< ", \"" << O
.FullName
<< "\", ";
93 OS
<< '\'' << O
.ShortName
<< "'";
95 // Decide if we have either an option, required or no argument for this
97 OS
<< ", OptionParser::";
98 if (!O
.ArgType
.empty()) {
100 OS
<< "eOptionalArgument";
102 OS
<< "eRequiredArgument";
107 if (!O
.Validator
.empty())
113 if (!O
.ArgType
.empty())
114 OS
<< "g_argument_table[eArgType" << O
.ArgType
<< "].enum_values";
119 // Read the tab completions we offer for this option (if there are any)
120 if (!O
.Completions
.empty()) {
121 std::vector
<std::string
> CompletionArgs
;
122 for (llvm::StringRef Completion
: O
.Completions
)
123 CompletionArgs
.push_back("e" + Completion
.str() + "Completion");
125 OS
<< llvm::join(CompletionArgs
.begin(), CompletionArgs
.end(), " | ");
127 OS
<< "CompletionType::eNoCompletion";
129 // Add the argument type.
131 if (!O
.ArgType
.empty()) {
137 // Add the description if there is any.
138 if (!O
.Description
.empty()) {
140 llvm::printEscapedString(O
.Description
, OS
);
147 /// Emits all option initializers to the raw_ostream.
148 static void emitOptions(std::string Command
, ArrayRef
<const Record
*> Records
,
150 std::vector
<CommandOption
> Options(Records
.begin(), Records
.end());
152 std::string ID
= Command
;
153 std::replace(ID
.begin(), ID
.end(), ' ', '_');
154 // Generate the macro that the user needs to define before including the
156 std::string NeededMacro
= "LLDB_OPTIONS_" + ID
;
158 // All options are in one file, so we need put them behind macros and ask the
159 // user to define the macro for the options that are needed.
160 OS
<< "// Options for " << Command
<< "\n";
161 OS
<< "#ifdef " << NeededMacro
<< "\n";
162 OS
<< "constexpr static OptionDefinition g_" + ID
+ "_options[] = {\n";
163 for (CommandOption
&CO
: Options
)
165 // We undefine the macro for the user like Clang's include files are doing it.
167 OS
<< "#undef " << NeededMacro
<< "\n";
168 OS
<< "#endif // " << Command
<< " command\n\n";
171 void lldb_private::EmitOptionDefs(const RecordKeeper
&Records
,
173 emitSourceFileHeader("Options for LLDB command line commands.", OS
, Records
);
175 ArrayRef
<const Record
*> Options
= Records
.getAllDerivedDefinitions("Option");
176 for (auto &CommandRecordPair
: getRecordsByName(Options
, "Command")) {
177 emitOptions(CommandRecordPair
.first
, CommandRecordPair
.second
, OS
);