1 //===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====// 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 // This tablegen backend emits command lists and efficient matchers for command 10 // names that are used in documentation comments. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "TableGenBackends.h" 15 16 #include "llvm/TableGen/Record.h" 17 #include "llvm/TableGen/StringMatcher.h" 18 #include "llvm/TableGen/TableGenBackend.h" 19 #include <vector> 20 21 using namespace llvm; 22 23 void clang::EmitClangCommentCommandInfo(RecordKeeper &Records, 24 raw_ostream &OS) { 25 emitSourceFileHeader("A list of commands useable in documentation comments", 26 OS, Records); 27 28 OS << "namespace {\n" 29 "const CommandInfo Commands[] = {\n"; 30 std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); 31 for (size_t i = 0, e = Tags.size(); i != e; ++i) { 32 Record &Tag = *Tags[i]; 33 OS << " { " 34 << "\"" << Tag.getValueAsString("Name") << "\", " 35 << "\"" << Tag.getValueAsString("EndCommandName") << "\", " 36 << i << ", " 37 << Tag.getValueAsInt("NumArgs") << ", " 38 << Tag.getValueAsBit("IsInlineCommand") << ", " 39 << Tag.getValueAsBit("IsBlockCommand") << ", " 40 << Tag.getValueAsBit("IsBriefCommand") << ", " 41 << Tag.getValueAsBit("IsReturnsCommand") << ", " 42 << Tag.getValueAsBit("IsParamCommand") << ", " 43 << Tag.getValueAsBit("IsTParamCommand") << ", " 44 << Tag.getValueAsBit("IsThrowsCommand") << ", " 45 << Tag.getValueAsBit("IsDeprecatedCommand") << ", " 46 << Tag.getValueAsBit("IsHeaderfileCommand") << ", " 47 << Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", " 48 << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", " 49 << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", " 50 << Tag.getValueAsBit("IsVerbatimLineCommand") << ", " 51 << Tag.getValueAsBit("IsDeclarationCommand") << ", " 52 << Tag.getValueAsBit("IsFunctionDeclarationCommand") << ", " 53 << Tag.getValueAsBit("IsRecordLikeDetailCommand") << ", " 54 << Tag.getValueAsBit("IsRecordLikeDeclarationCommand") << ", " 55 << /* IsUnknownCommand = */ "0" 56 << " }"; 57 if (i + 1 != e) 58 OS << ","; 59 OS << "\n"; 60 } 61 OS << "};\n" 62 "} // unnamed namespace\n\n"; 63 64 std::vector<StringMatcher::StringPair> Matches; 65 for (size_t i = 0, e = Tags.size(); i != e; ++i) { 66 Record &Tag = *Tags[i]; 67 std::string Name = std::string(Tag.getValueAsString("Name")); 68 std::string Return; 69 raw_string_ostream(Return) << "return &Commands[" << i << "];"; 70 Matches.emplace_back(std::move(Name), std::move(Return)); 71 } 72 73 OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n" 74 << " StringRef Name) {\n"; 75 StringMatcher("Name", Matches, OS).Emit(); 76 OS << " return nullptr;\n" 77 << "}\n\n"; 78 } 79 80 static std::string MangleName(StringRef Str) { 81 std::string Mangled; 82 for (unsigned i = 0, e = Str.size(); i != e; ++i) { 83 switch (Str[i]) { 84 default: 85 Mangled += Str[i]; 86 break; 87 case '(': 88 Mangled += "lparen"; 89 break; 90 case ')': 91 Mangled += "rparen"; 92 break; 93 case '[': 94 Mangled += "lsquare"; 95 break; 96 case ']': 97 Mangled += "rsquare"; 98 break; 99 case '{': 100 Mangled += "lbrace"; 101 break; 102 case '}': 103 Mangled += "rbrace"; 104 break; 105 case '$': 106 Mangled += "dollar"; 107 break; 108 case '/': 109 Mangled += "slash"; 110 break; 111 } 112 } 113 return Mangled; 114 } 115 116 void clang::EmitClangCommentCommandList(RecordKeeper &Records, 117 raw_ostream &OS) { 118 emitSourceFileHeader("A list of commands useable in documentation comments", 119 OS, Records); 120 121 OS << "#ifndef COMMENT_COMMAND\n" 122 << "# define COMMENT_COMMAND(NAME)\n" 123 << "#endif\n"; 124 125 std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); 126 for (size_t i = 0, e = Tags.size(); i != e; ++i) { 127 Record &Tag = *Tags[i]; 128 std::string MangledName = MangleName(Tag.getValueAsString("Name")); 129 130 OS << "COMMENT_COMMAND(" << MangledName << ")\n"; 131 } 132 } 133