1 //===- LLDBOptionDefEmitter.cpp -------------------------------------------===// 2 // 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" 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" 20 #include <vector> 21 22 using namespace llvm; 23 using namespace lldb_private; 24 25 namespace { 26 struct CommandOption { 27 std::vector<std::string> GroupsArg; 28 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; 37 38 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. 58 FullName = std::string(Option->getValueAsString("FullName")); 59 ShortName = std::string(Option->getValueAsString("ShortName")); 60 61 if (auto A = Option->getValue("ArgType")) 62 ArgType = A->getValue()->getAsUnquotedString(); 63 OptionalArg = Option->getValue("OptionalArg") != nullptr; 64 65 if (Option->getValue("Validator")) 66 Validator = std::string(Option->getValueAsString("Validator")); 67 68 if (Option->getValue("ArgEnum")) 69 ArgEnum = std::string(Option->getValueAsString("ArgEnum")); 70 71 if (Option->getValue("Completions")) 72 Completions = Option->getValueAsListOfStrings("Completions"); 73 74 if (auto D = Option->getValue("Description")) 75 Description = D->getValue()->getAsUnquotedString(); 76 } 77 }; 78 } // namespace 79 80 static void emitOption(const CommandOption &O, raw_ostream &OS) { 81 OS << " {"; 82 83 // If we have any groups, we merge them. Otherwise we move this option into 84 // the all group. 85 if (O.GroupsArg.empty()) 86 OS << "LLDB_OPT_SET_ALL"; 87 else 88 OS << llvm::join(O.GroupsArg.begin(), O.GroupsArg.end(), " | "); 89 90 OS << ", "; 91 92 // Check if this option is required. 93 OS << (O.Required ? "true" : "false"); 94 95 // Add the full and short name for this option. 96 OS << ", \"" << O.FullName << "\", "; 97 OS << '\'' << O.ShortName << "'"; 98 99 // Decide if we have either an option, required or no argument for this 100 // option. 101 OS << ", OptionParser::"; 102 if (!O.ArgType.empty()) { 103 if (O.OptionalArg) 104 OS << "eOptionalArgument"; 105 else 106 OS << "eRequiredArgument"; 107 } else 108 OS << "eNoArgument"; 109 OS << ", "; 110 111 if (!O.Validator.empty()) 112 OS << O.Validator; 113 else 114 OS << "nullptr"; 115 OS << ", "; 116 117 if (!O.ArgEnum.empty()) 118 OS << O.ArgEnum; 119 else 120 OS << "{}"; 121 OS << ", "; 122 123 // Read the tab completions we offer for this option (if there are any) 124 if (!O.Completions.empty()) { 125 std::vector<std::string> CompletionArgs; 126 for (llvm::StringRef Completion : O.Completions) 127 CompletionArgs.push_back("CommandCompletions::e" + Completion.str() + 128 "Completion"); 129 130 OS << llvm::join(CompletionArgs.begin(), CompletionArgs.end(), " | "); 131 } else 132 OS << "CommandCompletions::eNoCompletion"; 133 134 // Add the argument type. 135 OS << ", eArgType"; 136 if (!O.ArgType.empty()) { 137 OS << O.ArgType; 138 } else 139 OS << "None"; 140 OS << ", "; 141 142 // Add the description if there is any. 143 if (!O.Description.empty()) { 144 OS << "\""; 145 llvm::printEscapedString(O.Description, OS); 146 OS << "\""; 147 } else 148 OS << "\"\""; 149 OS << "},\n"; 150 } 151 152 /// Emits all option initializers to the raw_ostream. 153 static void emitOptions(std::string Command, std::vector<Record *> Records, 154 raw_ostream &OS) { 155 std::vector<CommandOption> Options; 156 for (Record *R : Records) 157 Options.emplace_back(R); 158 159 std::string ID = Command; 160 std::replace(ID.begin(), ID.end(), ' ', '_'); 161 // Generate the macro that the user needs to define before including the 162 // *.inc file. 163 std::string NeededMacro = "LLDB_OPTIONS_" + ID; 164 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"; 169 OS << "constexpr static OptionDefinition g_" + ID + "_options[] = {\n"; 170 for (CommandOption &CO : Options) 171 emitOption(CO, OS); 172 // We undefine the macro for the user like Clang's include files are doing it. 173 OS << "};\n"; 174 OS << "#undef " << NeededMacro << "\n"; 175 OS << "#endif // " << Command << " command\n\n"; 176 } 177 178 void lldb_private::EmitOptionDefs(RecordKeeper &Records, raw_ostream &OS) { 179 emitSourceFileHeader("Options for LLDB command line commands.", OS); 180 181 std::vector<Record *> Options = Records.getAllDerivedDefinitions("Option"); 182 for (auto &CommandRecordPair : getRecordsByName(Options, "Command")) { 183 emitOptions(CommandRecordPair.first, CommandRecordPair.second, OS); 184 } 185 } 186