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("CommandCompletions::e" + Completion.str() + 124 "Completion"); 125 126 OS << llvm::join(CompletionArgs.begin(), CompletionArgs.end(), " | "); 127 } else 128 OS << "CommandCompletions::eNoCompletion"; 129 130 // Add the argument type. 131 OS << ", eArgType"; 132 if (!O.ArgType.empty()) { 133 OS << O.ArgType; 134 } else 135 OS << "None"; 136 OS << ", "; 137 138 // Add the description if there is any. 139 if (!O.Description.empty()) { 140 OS << "\""; 141 llvm::printEscapedString(O.Description, OS); 142 OS << "\""; 143 } else 144 OS << "\"\""; 145 OS << "},\n"; 146 } 147 148 /// Emits all option initializers to the raw_ostream. 149 static void emitOptions(std::string Command, std::vector<Record *> Records, 150 raw_ostream &OS) { 151 std::vector<CommandOption> Options; 152 for (Record *R : Records) 153 Options.emplace_back(R); 154 155 std::string ID = Command; 156 std::replace(ID.begin(), ID.end(), ' ', '_'); 157 // Generate the macro that the user needs to define before including the 158 // *.inc file. 159 std::string NeededMacro = "LLDB_OPTIONS_" + ID; 160 161 // All options are in one file, so we need put them behind macros and ask the 162 // user to define the macro for the options that are needed. 163 OS << "// Options for " << Command << "\n"; 164 OS << "#ifdef " << NeededMacro << "\n"; 165 OS << "constexpr static OptionDefinition g_" + ID + "_options[] = {\n"; 166 for (CommandOption &CO : Options) 167 emitOption(CO, OS); 168 // We undefine the macro for the user like Clang's include files are doing it. 169 OS << "};\n"; 170 OS << "#undef " << NeededMacro << "\n"; 171 OS << "#endif // " << Command << " command\n\n"; 172 } 173 174 void lldb_private::EmitOptionDefs(RecordKeeper &Records, raw_ostream &OS) { 175 emitSourceFileHeader("Options for LLDB command line commands.", OS); 176 177 std::vector<Record *> Options = Records.getAllDerivedDefinitions("Option"); 178 for (auto &CommandRecordPair : getRecordsByName(Options, "Command")) { 179 emitOptions(CommandRecordPair.first, CommandRecordPair.second, OS); 180 } 181 } 182