1 //===-- Implementation of PublicAPICommand --------------------------------===// 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 #include "PublicAPICommand.h" 10 11 #include "utils/LibcTableGenUtil/APIIndexer.h" 12 13 #include "llvm/ADT/StringExtras.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/Support/SourceMgr.h" 16 #include "llvm/TableGen/Record.h" 17 18 // Text blocks for macro definitions and type decls can be indented to 19 // suit the surrounding tablegen listing. We need to dedent such blocks 20 // before writing them out. 21 static void dedentAndWrite(llvm::StringRef Text, llvm::raw_ostream &OS) { 22 llvm::SmallVector<llvm::StringRef, 10> Lines; 23 llvm::SplitString(Text, Lines, "\n"); 24 size_t shortest_indent = 1024; 25 for (llvm::StringRef L : Lines) { 26 llvm::StringRef Indent = L.take_while([](char c) { return c == ' '; }); 27 size_t IndentSize = Indent.size(); 28 if (Indent.size() == L.size()) { 29 // Line is all spaces so no point noting the indent. 30 continue; 31 } 32 if (IndentSize < shortest_indent) 33 shortest_indent = IndentSize; 34 } 35 for (llvm::StringRef L : Lines) { 36 if (L.size() >= shortest_indent) 37 OS << L.drop_front(shortest_indent) << '\n'; 38 } 39 } 40 41 namespace llvm_libc { 42 43 void writeAPIFromIndex(APIIndexer &G, llvm::raw_ostream &OS) { 44 for (auto &Pair : G.MacroDefsMap) { 45 const std::string &Name = Pair.first; 46 if (G.MacroSpecMap.find(Name) == G.MacroSpecMap.end()) 47 llvm::PrintFatalError(Name + " not found in any standard spec.\n"); 48 49 llvm::Record *MacroDef = Pair.second; 50 dedentAndWrite(MacroDef->getValueAsString("Defn"), OS); 51 52 OS << '\n'; 53 } 54 55 for (auto &Pair : G.TypeDeclsMap) { 56 const std::string &Name = Pair.first; 57 if (G.TypeSpecMap.find(Name) == G.TypeSpecMap.end()) 58 llvm::PrintFatalError(Name + " not found in any standard spec.\n"); 59 60 llvm::Record *TypeDecl = Pair.second; 61 dedentAndWrite(TypeDecl->getValueAsString("Decl"), OS); 62 63 OS << '\n'; 64 } 65 66 if (G.Enumerations.size() != 0) 67 OS << "enum {" << '\n'; 68 for (const auto &Name : G.Enumerations) { 69 if (G.EnumerationSpecMap.find(Name) == G.EnumerationSpecMap.end()) 70 llvm::PrintFatalError( 71 Name + " is not listed as an enumeration in any standard spec.\n"); 72 73 llvm::Record *EnumerationSpec = G.EnumerationSpecMap[Name]; 74 OS << " " << EnumerationSpec->getValueAsString("Name"); 75 auto Value = EnumerationSpec->getValueAsString("Value"); 76 if (Value == "__default__") { 77 OS << ",\n"; 78 } else { 79 OS << " = " << Value << ",\n"; 80 } 81 } 82 if (G.Enumerations.size() != 0) 83 OS << "};\n\n"; 84 85 OS << "__BEGIN_C_DECLS\n\n"; 86 for (auto &Name : G.Functions) { 87 if (G.FunctionSpecMap.find(Name) == G.FunctionSpecMap.end()) 88 llvm::PrintFatalError(Name + " not found in any standard spec.\n"); 89 90 llvm::Record *FunctionSpec = G.FunctionSpecMap[Name]; 91 llvm::Record *RetValSpec = FunctionSpec->getValueAsDef("Return"); 92 llvm::Record *ReturnType = RetValSpec->getValueAsDef("ReturnType"); 93 94 OS << G.getTypeAsString(ReturnType) << " " << Name << "("; 95 96 auto ArgsList = FunctionSpec->getValueAsListOfDefs("Args"); 97 for (size_t i = 0; i < ArgsList.size(); ++i) { 98 llvm::Record *ArgType = ArgsList[i]->getValueAsDef("ArgType"); 99 OS << G.getTypeAsString(ArgType); 100 if (i < ArgsList.size() - 1) 101 OS << ", "; 102 } 103 104 OS << ");\n\n"; 105 } 106 OS << "__END_C_DECLS\n"; 107 } 108 109 void writePublicAPI(llvm::raw_ostream &OS, llvm::RecordKeeper &Records) {} 110 111 const char PublicAPICommand::Name[] = "public_api"; 112 113 void PublicAPICommand::run(llvm::raw_ostream &OS, const ArgVector &Args, 114 llvm::StringRef StdHeader, 115 llvm::RecordKeeper &Records, 116 const Command::ErrorReporter &Reporter) const { 117 if (Args.size() != 0) { 118 Reporter.printFatalError("public_api command does not take any arguments."); 119 } 120 121 APIIndexer G(StdHeader, Records); 122 writeAPIFromIndex(G, OS); 123 } 124 125 } // namespace llvm_libc 126