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