blob: ccf48275f42c0fc81878ebeb94b11969735cc06a [file] [log] [blame]
Jonas Devlieghere9870f6a2019-07-25 04:38:46 +00001//===- LLDBOptionDefEmitter.cpp -------------------------------------------===//
Jonas Devlieghere93f50592019-07-23 17:47:08 +00002//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// These tablegen backends emits LLDB's OptionDefinition values for different
10// LLDB commands.
11//
12//===----------------------------------------------------------------------===//
13
14#include "LLDBTableGenBackends.h"
Jonas Devliegherebe019c72019-07-31 00:47:00 +000015#include "LLDBTableGenUtils.h"
Jonas Devlieghere93f50592019-07-23 17:47:08 +000016#include "llvm/ADT/StringExtras.h"
17#include "llvm/TableGen/Record.h"
18#include "llvm/TableGen/StringMatcher.h"
19#include "llvm/TableGen/TableGenBackend.h"
Jonas Devlieghere93f50592019-07-23 17:47:08 +000020#include <vector>
21
22using namespace llvm;
Jonas Devlieghere310f6b82019-07-30 22:50:37 +000023using namespace lldb_private;
Jonas Devlieghere93f50592019-07-23 17:47:08 +000024
Raphael Isemann4e44c772019-07-29 08:22:41 +000025namespace {
26struct CommandOption {
Jonas Devlieghere93f50592019-07-23 17:47:08 +000027 std::vector<std::string> GroupsArg;
Raphael Isemann4e44c772019-07-29 08:22:41 +000028 bool Required = false;
29 std::string FullName;
30 std::string ShortName;
31 std::string ArgType;
32 bool OptionalArg = false;
33 std::string Validator;
34 std::string ArgEnum;
35 std::vector<StringRef> Completions;
36 std::string Description;
Jonas Devlieghere93f50592019-07-23 17:47:08 +000037
Raphael Isemann4e44c772019-07-29 08:22:41 +000038 CommandOption() = default;
39 CommandOption(Record *Option) {
40 if (Option->getValue("Groups")) {
41 // The user specified a list of groups.
42 auto Groups = Option->getValueAsListOfInts("Groups");
43 for (int Group : Groups)
44 GroupsArg.push_back("LLDB_OPT_SET_" + std::to_string(Group));
45 } else if (Option->getValue("GroupStart")) {
46 // The user specified a range of groups (with potentially only one
47 // element).
48 int GroupStart = Option->getValueAsInt("GroupStart");
49 int GroupEnd = Option->getValueAsInt("GroupEnd");
50 for (int i = GroupStart; i <= GroupEnd; ++i)
51 GroupsArg.push_back("LLDB_OPT_SET_" + std::to_string(i));
52 }
53
54 // Check if this option is required.
55 Required = Option->getValue("Required");
56
57 // Add the full and short name for this option.
Benjamin Krameradcd0262020-01-28 20:23:46 +010058 FullName = std::string(Option->getValueAsString("FullName"));
59 ShortName = std::string(Option->getValueAsString("ShortName"));
Raphael Isemann4e44c772019-07-29 08:22:41 +000060
61 if (auto A = Option->getValue("ArgType"))
62 ArgType = A->getValue()->getAsUnquotedString();
63 OptionalArg = Option->getValue("OptionalArg") != nullptr;
64
65 if (Option->getValue("Validator"))
Benjamin Krameradcd0262020-01-28 20:23:46 +010066 Validator = std::string(Option->getValueAsString("Validator"));
Raphael Isemann4e44c772019-07-29 08:22:41 +000067
68 if (Option->getValue("ArgEnum"))
Benjamin Krameradcd0262020-01-28 20:23:46 +010069 ArgEnum = std::string(Option->getValueAsString("ArgEnum"));
Raphael Isemann4e44c772019-07-29 08:22:41 +000070
71 if (Option->getValue("Completions"))
72 Completions = Option->getValueAsListOfStrings("Completions");
73
74 if (auto D = Option->getValue("Description"))
75 Description = D->getValue()->getAsUnquotedString();
Jonas Devlieghere93f50592019-07-23 17:47:08 +000076 }
Raphael Isemann4e44c772019-07-29 08:22:41 +000077};
78} // namespace
79
80static void emitOption(const CommandOption &O, raw_ostream &OS) {
81 OS << " {";
Jonas Devlieghere93f50592019-07-23 17:47:08 +000082
83 // If we have any groups, we merge them. Otherwise we move this option into
84 // the all group.
Raphael Isemann4e44c772019-07-29 08:22:41 +000085 if (O.GroupsArg.empty())
Jonas Devlieghere93f50592019-07-23 17:47:08 +000086 OS << "LLDB_OPT_SET_ALL";
87 else
Raphael Isemann4e44c772019-07-29 08:22:41 +000088 OS << llvm::join(O.GroupsArg.begin(), O.GroupsArg.end(), " | ");
Jonas Devlieghere93f50592019-07-23 17:47:08 +000089
90 OS << ", ";
91
92 // Check if this option is required.
Raphael Isemann4e44c772019-07-29 08:22:41 +000093 OS << (O.Required ? "true" : "false");
Jonas Devlieghere93f50592019-07-23 17:47:08 +000094
95 // Add the full and short name for this option.
Raphael Isemann4e44c772019-07-29 08:22:41 +000096 OS << ", \"" << O.FullName << "\", ";
97 OS << '\'' << O.ShortName << "'";
Jonas Devlieghere93f50592019-07-23 17:47:08 +000098
99 // Decide if we have either an option, required or no argument for this
100 // option.
101 OS << ", OptionParser::";
Raphael Isemann4e44c772019-07-29 08:22:41 +0000102 if (!O.ArgType.empty()) {
103 if (O.OptionalArg)
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000104 OS << "eOptionalArgument";
105 else
106 OS << "eRequiredArgument";
107 } else
108 OS << "eNoArgument";
Raphael Isemann0ab0bb92019-07-26 11:46:21 +0000109 OS << ", ";
110
Raphael Isemann4e44c772019-07-29 08:22:41 +0000111 if (!O.Validator.empty())
112 OS << O.Validator;
Raphael Isemann0ab0bb92019-07-26 11:46:21 +0000113 else
114 OS << "nullptr";
115 OS << ", ";
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000116
Raphael Isemann4e44c772019-07-29 08:22:41 +0000117 if (!O.ArgEnum.empty())
118 OS << O.ArgEnum;
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000119 else
120 OS << "{}";
121 OS << ", ";
122
123 // Read the tab completions we offer for this option (if there are any)
Raphael Isemann4e44c772019-07-29 08:22:41 +0000124 if (!O.Completions.empty()) {
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000125 std::vector<std::string> CompletionArgs;
Raphael Isemann4e44c772019-07-29 08:22:41 +0000126 for (llvm::StringRef Completion : O.Completions)
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000127 CompletionArgs.push_back("CommandCompletions::e" + Completion.str() +
128 "Completion");
129
130 OS << llvm::join(CompletionArgs.begin(), CompletionArgs.end(), " | ");
Raphael Isemann4e44c772019-07-29 08:22:41 +0000131 } else
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000132 OS << "CommandCompletions::eNoCompletion";
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000133
134 // Add the argument type.
135 OS << ", eArgType";
Raphael Isemann4e44c772019-07-29 08:22:41 +0000136 if (!O.ArgType.empty()) {
137 OS << O.ArgType;
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000138 } else
139 OS << "None";
140 OS << ", ";
141
142 // Add the description if there is any.
Raphael Isemann4e44c772019-07-29 08:22:41 +0000143 if (!O.Description.empty()) {
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000144 OS << "\"";
Raphael Isemann4e44c772019-07-29 08:22:41 +0000145 llvm::printEscapedString(O.Description, OS);
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000146 OS << "\"";
147 } else
148 OS << "\"\"";
149 OS << "},\n";
150}
151
152/// Emits all option initializers to the raw_ostream.
Raphael Isemann4e44c772019-07-29 08:22:41 +0000153static void emitOptions(std::string Command, std::vector<Record *> Records,
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000154 raw_ostream &OS) {
Raphael Isemann4e44c772019-07-29 08:22:41 +0000155 std::vector<CommandOption> Options;
156 for (Record *R : Records)
157 Options.emplace_back(R);
158
Raphael Isemannbd68a052019-07-28 06:24:07 +0000159 std::string ID = Command;
160 std::replace(ID.begin(), ID.end(), ' ', '_');
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000161 // Generate the macro that the user needs to define before including the
162 // *.inc file.
Raphael Isemannbd68a052019-07-28 06:24:07 +0000163 std::string NeededMacro = "LLDB_OPTIONS_" + ID;
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000164
165 // All options are in one file, so we need put them behind macros and ask the
166 // user to define the macro for the options that are needed.
167 OS << "// Options for " << Command << "\n";
168 OS << "#ifdef " << NeededMacro << "\n";
Raphael Isemannbd68a052019-07-28 06:24:07 +0000169 OS << "constexpr static OptionDefinition g_" + ID + "_options[] = {\n";
Raphael Isemann4e44c772019-07-29 08:22:41 +0000170 for (CommandOption &CO : Options)
171 emitOption(CO, OS);
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000172 // We undefine the macro for the user like Clang's include files are doing it.
Raphael Isemannbd68a052019-07-28 06:24:07 +0000173 OS << "};\n";
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000174 OS << "#undef " << NeededMacro << "\n";
175 OS << "#endif // " << Command << " command\n\n";
176}
177
178void lldb_private::EmitOptionDefs(RecordKeeper &Records, raw_ostream &OS) {
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000179 emitSourceFileHeader("Options for LLDB command line commands.", OS);
180
Jonas Devlieghere310f6b82019-07-30 22:50:37 +0000181 std::vector<Record *> Options = Records.getAllDerivedDefinitions("Option");
Jonas Devliegherebe019c72019-07-31 00:47:00 +0000182 for (auto &CommandRecordPair : getRecordsByName(Options, "Command")) {
Jonas Devlieghere93f50592019-07-23 17:47:08 +0000183 emitOptions(CommandRecordPair.first, CommandRecordPair.second, OS);
184 }
185}