1 2 #include "APIIndexer.h" 3 4 #include "llvm/ADT/StringExtras.h" 5 #include "llvm/ADT/StringRef.h" 6 #include "llvm/TableGen/Error.h" 7 #include "llvm/TableGen/Record.h" 8 9 namespace llvm_libc { 10 11 static const char NamedTypeClassName[] = "NamedType"; 12 static const char PtrTypeClassName[] = "PtrType"; 13 static const char RestrictedPtrTypeClassName[] = "RestrictedPtrType"; 14 static const char ConstTypeClassName[] = "ConstType"; 15 static const char StructTypeClassName[] = "Struct"; 16 17 static const char StandardSpecClassName[] = "StandardSpec"; 18 static const char PublicAPIClassName[] = "PublicAPI"; 19 20 static bool isa(llvm::Record *Def, llvm::Record *TypeClass) { 21 llvm::RecordRecTy *RecordType = Def->getType(); 22 llvm::ArrayRef<llvm::Record *> Classes = RecordType->getClasses(); 23 // We want exact types. That is, we don't want the classes listed in 24 // spec.td to be subclassed. Hence, we do not want the record |Def| 25 // to be of more than one class type.. 26 if (Classes.size() != 1) 27 return false; 28 return Classes[0] == TypeClass; 29 } 30 31 bool APIIndexer::isaNamedType(llvm::Record *Def) { 32 return isa(Def, NamedTypeClass); 33 } 34 35 bool APIIndexer::isaStructType(llvm::Record *Def) { 36 return isa(Def, StructClass); 37 } 38 39 bool APIIndexer::isaPtrType(llvm::Record *Def) { 40 return isa(Def, PtrTypeClass); 41 } 42 43 bool APIIndexer::isaConstType(llvm::Record *Def) { 44 return isa(Def, ConstTypeClass); 45 } 46 47 bool APIIndexer::isaRestrictedPtrType(llvm::Record *Def) { 48 return isa(Def, RestrictedPtrTypeClass); 49 } 50 51 bool APIIndexer::isaStandardSpec(llvm::Record *Def) { 52 return isa(Def, StandardSpecClass); 53 } 54 55 bool APIIndexer::isaPublicAPI(llvm::Record *Def) { 56 return isa(Def, PublicAPIClass); 57 } 58 59 std::string APIIndexer::getTypeAsString(llvm::Record *TypeRecord) { 60 if (isaNamedType(TypeRecord) || isaStructType(TypeRecord)) { 61 return std::string(TypeRecord->getValueAsString("Name")); 62 } else if (isaPtrType(TypeRecord)) { 63 return getTypeAsString(TypeRecord->getValueAsDef("PointeeType")) + " *"; 64 } else if (isaConstType(TypeRecord)) { 65 return std::string("const ") + 66 getTypeAsString(TypeRecord->getValueAsDef("UnqualifiedType")); 67 } else if (isaRestrictedPtrType(TypeRecord)) { 68 return getTypeAsString(TypeRecord->getValueAsDef("PointeeType")) + 69 " *__restrict"; 70 } else { 71 llvm::PrintFatalError(TypeRecord->getLoc(), "Invalid type.\n"); 72 } 73 } 74 75 void APIIndexer::indexStandardSpecDef(llvm::Record *StandardSpec) { 76 auto HeaderSpecList = StandardSpec->getValueAsListOfDefs("Headers"); 77 for (llvm::Record *HeaderSpec : HeaderSpecList) { 78 llvm::StringRef Header = HeaderSpec->getValueAsString("Name"); 79 if (!StdHeader.hasValue() || Header == StdHeader) { 80 PublicHeaders.emplace(Header); 81 auto MacroSpecList = HeaderSpec->getValueAsListOfDefs("Macros"); 82 // TODO: Trigger a fatal error on duplicate specs. 83 for (llvm::Record *MacroSpec : MacroSpecList) 84 MacroSpecMap[std::string(MacroSpec->getValueAsString("Name"))] = 85 MacroSpec; 86 87 auto TypeSpecList = HeaderSpec->getValueAsListOfDefs("Types"); 88 for (llvm::Record *TypeSpec : TypeSpecList) 89 TypeSpecMap[std::string(TypeSpec->getValueAsString("Name"))] = TypeSpec; 90 91 auto FunctionSpecList = HeaderSpec->getValueAsListOfDefs("Functions"); 92 for (llvm::Record *FunctionSpec : FunctionSpecList) { 93 FunctionSpecMap[std::string(FunctionSpec->getValueAsString("Name"))] = 94 FunctionSpec; 95 } 96 97 auto EnumerationSpecList = 98 HeaderSpec->getValueAsListOfDefs("Enumerations"); 99 for (llvm::Record *EnumerationSpec : EnumerationSpecList) { 100 EnumerationSpecMap[std::string( 101 EnumerationSpec->getValueAsString("Name"))] = EnumerationSpec; 102 } 103 } 104 } 105 } 106 107 void APIIndexer::indexPublicAPIDef(llvm::Record *PublicAPI) { 108 // While indexing the public API, we do not check if any of the entities 109 // requested is from an included standard. Such a check is done while 110 // generating the API. 111 auto MacroDefList = PublicAPI->getValueAsListOfDefs("Macros"); 112 for (llvm::Record *MacroDef : MacroDefList) 113 MacroDefsMap[std::string(MacroDef->getValueAsString("Name"))] = MacroDef; 114 115 auto TypeDeclList = PublicAPI->getValueAsListOfDefs("TypeDeclarations"); 116 for (llvm::Record *TypeDecl : TypeDeclList) 117 TypeDeclsMap[std::string(TypeDecl->getValueAsString("Name"))] = TypeDecl; 118 119 auto StructList = PublicAPI->getValueAsListOfStrings("Structs"); 120 for (llvm::StringRef StructName : StructList) 121 Structs.insert(std::string(StructName)); 122 123 auto FunctionList = PublicAPI->getValueAsListOfStrings("Functions"); 124 for (llvm::StringRef FunctionName : FunctionList) 125 Functions.insert(std::string(FunctionName)); 126 127 auto EnumerationList = PublicAPI->getValueAsListOfStrings("Enumerations"); 128 for (llvm::StringRef EnumerationName : EnumerationList) 129 Enumerations.insert(std::string(EnumerationName)); 130 } 131 132 void APIIndexer::index(llvm::RecordKeeper &Records) { 133 NamedTypeClass = Records.getClass(NamedTypeClassName); 134 PtrTypeClass = Records.getClass(PtrTypeClassName); 135 RestrictedPtrTypeClass = Records.getClass(RestrictedPtrTypeClassName); 136 StructClass = Records.getClass(StructTypeClassName); 137 ConstTypeClass = Records.getClass(ConstTypeClassName); 138 StandardSpecClass = Records.getClass(StandardSpecClassName); 139 PublicAPIClass = Records.getClass(PublicAPIClassName); 140 141 const auto &DefsMap = Records.getDefs(); 142 for (auto &Pair : DefsMap) { 143 llvm::Record *Def = Pair.second.get(); 144 if (isaStandardSpec(Def)) 145 indexStandardSpecDef(Def); 146 if (isaPublicAPI(Def)) { 147 if (!StdHeader.hasValue() || 148 Def->getValueAsString("HeaderName") == StdHeader) 149 indexPublicAPIDef(Def); 150 } 151 } 152 } 153 154 } // namespace llvm_libc 155