summaryrefslogtreecommitdiffstats
path: root/lldb/utils/TableGen/LLDBOptionDefEmitter.cpp
diff options
context:
space:
mode:
authorRaphael Isemann <teemperor@gmail.com>2019-07-12 15:30:55 +0000
committerRaphael Isemann <teemperor@gmail.com>2019-07-12 15:30:55 +0000
commit6f4fb4e7ad67499391dd5b63ad9f5a11b1c74171 (patch)
tree99d03447ee96b18f63f9134d7c8291dc6c5437ad /lldb/utils/TableGen/LLDBOptionDefEmitter.cpp
parent38cd364007a928d1a1f8d0768a1020a25a54de76 (diff)
downloadbcm5719-llvm-6f4fb4e7ad67499391dd5b63ad9f5a11b1c74171.tar.gz
bcm5719-llvm-6f4fb4e7ad67499391dd5b63ad9f5a11b1c74171.zip
[lldb] Let table gen create command option initializers.
Summary: We currently have man large arrays containing initializers for our command options. These tables are tricky maintain as we don't have any good place to check them for consistency and it's also hard to read (`nullptr, {}, 0` is not very descriptive). This patch fixes this by letting table gen generate those tables. This way we can have a more readable syntax for this (especially for all the default arguments) and we can let TableCheck check them for consistency (e.g. an option with an optional argument can't have `eArgTypeNone`, naming of flags', etc.). Also refactoring the related data structures can now be done without changing the hundred of option initializers. For example, this line: ``` {LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Hide aliases in the command list."}, ``` becomes this: ``` def hide_aliases : Option<"hide-aliases", "a">, Desc<"Hide aliases in the command list.">; ``` For now I just moved a few initializers to the new format to demonstrate the change. I'll slowly migrate the other option initializers tables in separate patches. Reviewers: JDevlieghere, davide, sgraenitz Reviewed By: JDevlieghere Subscribers: jingham, xiaobai, labath, mgorny, abidh, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D64365 llvm-svn: 365908
Diffstat (limited to 'lldb/utils/TableGen/LLDBOptionDefEmitter.cpp')
-rw-r--r--lldb/utils/TableGen/LLDBOptionDefEmitter.cpp152
1 files changed, 152 insertions, 0 deletions
diff --git a/lldb/utils/TableGen/LLDBOptionDefEmitter.cpp b/lldb/utils/TableGen/LLDBOptionDefEmitter.cpp
new file mode 100644
index 00000000000..00b44c020a2
--- /dev/null
+++ b/lldb/utils/TableGen/LLDBOptionDefEmitter.cpp
@@ -0,0 +1,152 @@
+//===- TableGen.cpp - Top-Level TableGen implementation for Clang ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emits LLDB's OptionDefinition values for different
+// LLDB commands.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LLDBTableGenBackends.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <map>
+#include <vector>
+
+using namespace llvm;
+
+/// Map of command names to their associated records. Also makes sure our
+/// commands are sorted in a deterministic way.
+typedef std::map<std::string, std::vector<Record *>> RecordsByCommand;
+
+/// Groups all records by their command.
+static RecordsByCommand getCommandList(std::vector<Record *> Options) {
+ RecordsByCommand result;
+ for (Record *Option : Options)
+ result[Option->getValueAsString("Command").str()].push_back(Option);
+ return result;
+}
+
+static void emitOption(Record *Option, raw_ostream &OS) {
+ OS << " {";
+
+ // List of option groups this option is in.
+ std::vector<std::string> GroupsArg;
+
+ if (Option->getValue("Groups")) {
+ // The user specified a list of groups.
+ auto Groups = Option->getValueAsListOfInts("Groups");
+ for (int Group : Groups)
+ GroupsArg.push_back("LLDB_OPT_SET_" + std::to_string(Group));
+ OS << llvm::join(GroupsArg.begin(), GroupsArg.end(), " | ");
+ } else if (Option->getValue("GroupStart")) {
+ // The user specified a range of groups (with potentially only one element).
+ int GroupStart = Option->getValueAsInt("GroupStart");
+ int GroupEnd = Option->getValueAsInt("GroupEnd");
+ for (int i = GroupStart; i <= GroupEnd; ++i)
+ GroupsArg.push_back("LLDB_OPT_SET_" + std::to_string(i));
+ }
+
+ // If we have any groups, we merge them. Otherwise we move this option into
+ // the all group.
+ if (GroupsArg.empty())
+ OS << "LLDB_OPT_SET_ALL";
+ else
+ OS << llvm::join(GroupsArg.begin(), GroupsArg.end(), " | ");
+
+ OS << ", ";
+
+ // Check if this option is required.
+ OS << (Option->getValue("Required") ? "true" : "false");
+
+ // Add the full and short name for this option.
+ OS << ", \"" << Option->getValueAsString("FullName") << "\", ";
+ OS << '\'' << Option->getValueAsString("ShortName") << "'";
+
+ auto ArgType = Option->getValue("ArgType");
+ bool IsOptionalArg = Option->getValue("OptionalArg") != nullptr;
+
+ // Decide if we have either an option, required or no argument for this
+ // option.
+ OS << ", OptionParser::";
+ if (ArgType) {
+ if (IsOptionalArg)
+ OS << "eOptionalArgument";
+ else
+ OS << "eRequiredArgument";
+ } else
+ OS << "eNoArgument";
+ OS << ", nullptr, ";
+
+ if (Option->getValue("ArgEnum"))
+ OS << Option->getValueAsString("ArgEnum");
+ else
+ OS << "{}";
+ OS << ", ";
+
+ // Read the tab completions we offer for this option (if there are any)
+ if (Option->getValue("Completions")) {
+ auto Completions = Option->getValueAsListOfStrings("Completions");
+ std::vector<std::string> CompletionArgs;
+ for (llvm::StringRef Completion : Completions)
+ CompletionArgs.push_back("CommandCompletions::e" + Completion.str() +
+ "Completion");
+
+ OS << llvm::join(CompletionArgs.begin(), CompletionArgs.end(), " | ");
+ } else {
+ OS << "CommandCompletions::eNoCompletion";
+ }
+
+ // Add the argument type.
+ OS << ", eArgType";
+ if (ArgType) {
+ OS << ArgType->getValue()->getAsUnquotedString();
+ } else
+ OS << "None";
+ OS << ", ";
+
+ // Add the description if there is any.
+ if (auto D = Option->getValue("Description"))
+ OS << D->getValue()->getAsString();
+ else
+ OS << "\"\"";
+ OS << "},\n";
+}
+
+/// Emits all option initializers to the raw_ostream.
+static void emitOptions(std::string Command, std::vector<Record *> Option,
+ raw_ostream &OS) {
+ // Generate the macro that the user needs to define before including the
+ // *.inc file.
+ std::string NeededMacro = "LLDB_OPTIONS_" + Command;
+ std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_');
+
+ // All options are in one file, so we need put them behind macros and ask the
+ // user to define the macro for the options that are needed.
+ OS << "// Options for " << Command << "\n";
+ OS << "#ifdef " << NeededMacro << "\n";
+ for (Record *R : Option)
+ emitOption(R, OS);
+ // We undefine the macro for the user like Clang's include files are doing it.
+ OS << "#undef " << NeededMacro << "\n";
+ OS << "#endif // " << Command << " command\n\n";
+}
+
+void lldb_private::EmitOptionDefs(RecordKeeper &Records, raw_ostream &OS) {
+
+ std::vector<Record *> Options = Records.getAllDerivedDefinitions("Option");
+
+ emitSourceFileHeader("Options for LLDB command line commands.", OS);
+
+ RecordsByCommand ByCommand = getCommandList(Options);
+
+ for (auto &CommandRecordPair : ByCommand) {
+ emitOptions(CommandRecordPair.first, CommandRecordPair.second, OS);
+ }
+}
OpenPOWER on IntegriCloud