aboutsummaryrefslogtreecommitdiff
path: root/lldb/utils
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
parent38cd364007a928d1a1f8d0768a1020a25a54de76 (diff)
downloadllvm-6f4fb4e7ad67499391dd5b63ad9f5a11b1c74171.zip
llvm-6f4fb4e7ad67499391dd5b63ad9f5a11b1c74171.tar.gz
llvm-6f4fb4e7ad67499391dd5b63ad9f5a11b1c74171.tar.bz2
[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')
-rw-r--r--lldb/utils/TableGen/CMakeLists.txt8
-rw-r--r--lldb/utils/TableGen/LLDBOptionDefEmitter.cpp152
-rw-r--r--lldb/utils/TableGen/LLDBTableGen.cpp71
-rw-r--r--lldb/utils/TableGen/LLDBTableGenBackends.h34
4 files changed, 265 insertions, 0 deletions
diff --git a/lldb/utils/TableGen/CMakeLists.txt b/lldb/utils/TableGen/CMakeLists.txt
new file mode 100644
index 0000000..76e81916
--- /dev/null
+++ b/lldb/utils/TableGen/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(LLVM_LINK_COMPONENTS Support)
+
+add_tablegen(lldb-tblgen LLDB
+ LLDBOptionDefEmitter.cpp
+ LLDBTableGen.cpp
+ )
+set_target_properties(lldb-tblgen PROPERTIES FOLDER "LLDB tablegenning")
+
diff --git a/lldb/utils/TableGen/LLDBOptionDefEmitter.cpp b/lldb/utils/TableGen/LLDBOptionDefEmitter.cpp
new file mode 100644
index 0000000..00b44c02
--- /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);
+ }
+}
diff --git a/lldb/utils/TableGen/LLDBTableGen.cpp b/lldb/utils/TableGen/LLDBTableGen.cpp
new file mode 100644
index 0000000..9325fe0
--- /dev/null
+++ b/lldb/utils/TableGen/LLDBTableGen.cpp
@@ -0,0 +1,71 @@
+//===- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the main function for Clang's TableGen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LLDBTableGenBackends.h" // Declares all backends.
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Main.h"
+#include "llvm/TableGen/Record.h"
+
+using namespace llvm;
+using namespace lldb_private;
+
+enum ActionType {
+ PrintRecords,
+ DumpJSON,
+ GenOptionDefs,
+};
+
+static cl::opt<ActionType>
+ Action(cl::desc("Action to perform:"),
+ cl::values(clEnumValN(PrintRecords, "print-records",
+ "Print all records to stdout (default)"),
+ clEnumValN(DumpJSON, "dump-json",
+ "Dump all records as machine-readable JSON"),
+ clEnumValN(GenOptionDefs, "gen-lldb-option-defs",
+ "Generate clang attribute clases")));
+
+static bool LLDBTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
+ switch (Action) {
+ case PrintRecords:
+ OS << Records; // No argument, dump all contents
+ break;
+ case DumpJSON:
+ EmitJSON(Records, OS);
+ break;
+ case GenOptionDefs:
+ EmitOptionDefs(Records, OS);
+ break;
+ }
+ return false;
+}
+
+int main(int argc, char **argv) {
+ sys::PrintStackTraceOnErrorSignal(argv[0]);
+ PrettyStackTraceProgram X(argc, argv);
+ cl::ParseCommandLineOptions(argc, argv);
+
+ llvm_shutdown_obj Y;
+
+ return TableGenMain(argv[0], &LLDBTableGenMain);
+}
+
+#ifdef __has_feature
+#if __has_feature(address_sanitizer)
+#include <sanitizer/lsan_interface.h>
+// Disable LeakSanitizer for this binary as it has too many leaks that are not
+// very interesting to fix. See compiler-rt/include/sanitizer/lsan_interface.h .
+int __lsan_is_turned_off() { return 1; }
+#endif // __has_feature(address_sanitizer)
+#endif // defined(__has_feature)
diff --git a/lldb/utils/TableGen/LLDBTableGenBackends.h b/lldb/utils/TableGen/LLDBTableGenBackends.h
new file mode 100644
index 0000000..eb14d80
--- /dev/null
+++ b/lldb/utils/TableGen/LLDBTableGenBackends.h
@@ -0,0 +1,34 @@
+//===- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declarations for all of the LLDB TableGen
+// backends. A "TableGen backend" is just a function. See
+// "$LLVM_ROOT/utils/TableGen/TableGenBackends.h" for more info.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LLDB_UTILS_TABLEGEN_TABLEGENBACKENDS_H
+#define LLVM_LLDB_UTILS_TABLEGEN_TABLEGENBACKENDS_H
+
+#include <string>
+
+namespace llvm {
+class raw_ostream;
+class RecordKeeper;
+} // namespace llvm
+
+using llvm::raw_ostream;
+using llvm::RecordKeeper;
+
+namespace lldb_private {
+
+void EmitOptionDefs(RecordKeeper &RK, raw_ostream &OS);
+
+} // namespace lldb_private
+
+#endif