133abb729SChris Gyurgyik //===-- Implementation of APIIndexer class --------------------------------===//
2cd7a5c3cSSiva Chandra Reddy //
3cd7a5c3cSSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4cd7a5c3cSSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
5cd7a5c3cSSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cd7a5c3cSSiva Chandra Reddy //
7cd7a5c3cSSiva Chandra Reddy //===----------------------------------------------------------------------===//
859f17a7dSSiva Chandra Reddy
959f17a7dSSiva Chandra Reddy #include "APIIndexer.h"
1059f17a7dSSiva Chandra Reddy
1159f17a7dSSiva Chandra Reddy #include "llvm/ADT/StringExtras.h"
1259f17a7dSSiva Chandra Reddy #include "llvm/ADT/StringRef.h"
1359f17a7dSSiva Chandra Reddy #include "llvm/TableGen/Error.h"
1459f17a7dSSiva Chandra Reddy #include "llvm/TableGen/Record.h"
1559f17a7dSSiva Chandra Reddy
1659f17a7dSSiva Chandra Reddy namespace llvm_libc {
1759f17a7dSSiva Chandra Reddy
1859f17a7dSSiva Chandra Reddy static const char NamedTypeClassName[] = "NamedType";
1959f17a7dSSiva Chandra Reddy static const char PtrTypeClassName[] = "PtrType";
2059f17a7dSSiva Chandra Reddy static const char RestrictedPtrTypeClassName[] = "RestrictedPtrType";
2159f17a7dSSiva Chandra Reddy static const char ConstTypeClassName[] = "ConstType";
2259f17a7dSSiva Chandra Reddy static const char StructTypeClassName[] = "Struct";
2359f17a7dSSiva Chandra Reddy
2459f17a7dSSiva Chandra Reddy static const char StandardSpecClassName[] = "StandardSpec";
2559f17a7dSSiva Chandra Reddy static const char PublicAPIClassName[] = "PublicAPI";
2659f17a7dSSiva Chandra Reddy
isa(llvm::Record * Def,llvm::Record * TypeClass)2759f17a7dSSiva Chandra Reddy static bool isa(llvm::Record *Def, llvm::Record *TypeClass) {
2859f17a7dSSiva Chandra Reddy llvm::RecordRecTy *RecordType = Def->getType();
2959f17a7dSSiva Chandra Reddy llvm::ArrayRef<llvm::Record *> Classes = RecordType->getClasses();
3059f17a7dSSiva Chandra Reddy // We want exact types. That is, we don't want the classes listed in
3159f17a7dSSiva Chandra Reddy // spec.td to be subclassed. Hence, we do not want the record |Def|
3259f17a7dSSiva Chandra Reddy // to be of more than one class type..
3359f17a7dSSiva Chandra Reddy if (Classes.size() != 1)
3459f17a7dSSiva Chandra Reddy return false;
3559f17a7dSSiva Chandra Reddy return Classes[0] == TypeClass;
3659f17a7dSSiva Chandra Reddy }
3759f17a7dSSiva Chandra Reddy
isaNamedType(llvm::Record * Def)3859f17a7dSSiva Chandra Reddy bool APIIndexer::isaNamedType(llvm::Record *Def) {
3959f17a7dSSiva Chandra Reddy return isa(Def, NamedTypeClass);
4059f17a7dSSiva Chandra Reddy }
4159f17a7dSSiva Chandra Reddy
isaStructType(llvm::Record * Def)4259f17a7dSSiva Chandra Reddy bool APIIndexer::isaStructType(llvm::Record *Def) {
4359f17a7dSSiva Chandra Reddy return isa(Def, StructClass);
4459f17a7dSSiva Chandra Reddy }
4559f17a7dSSiva Chandra Reddy
isaPtrType(llvm::Record * Def)4659f17a7dSSiva Chandra Reddy bool APIIndexer::isaPtrType(llvm::Record *Def) {
4759f17a7dSSiva Chandra Reddy return isa(Def, PtrTypeClass);
4859f17a7dSSiva Chandra Reddy }
4959f17a7dSSiva Chandra Reddy
isaConstType(llvm::Record * Def)5059f17a7dSSiva Chandra Reddy bool APIIndexer::isaConstType(llvm::Record *Def) {
5159f17a7dSSiva Chandra Reddy return isa(Def, ConstTypeClass);
5259f17a7dSSiva Chandra Reddy }
5359f17a7dSSiva Chandra Reddy
isaRestrictedPtrType(llvm::Record * Def)5459f17a7dSSiva Chandra Reddy bool APIIndexer::isaRestrictedPtrType(llvm::Record *Def) {
5559f17a7dSSiva Chandra Reddy return isa(Def, RestrictedPtrTypeClass);
5659f17a7dSSiva Chandra Reddy }
5759f17a7dSSiva Chandra Reddy
isaStandardSpec(llvm::Record * Def)5859f17a7dSSiva Chandra Reddy bool APIIndexer::isaStandardSpec(llvm::Record *Def) {
5959f17a7dSSiva Chandra Reddy return isa(Def, StandardSpecClass);
6059f17a7dSSiva Chandra Reddy }
6159f17a7dSSiva Chandra Reddy
isaPublicAPI(llvm::Record * Def)6259f17a7dSSiva Chandra Reddy bool APIIndexer::isaPublicAPI(llvm::Record *Def) {
6359f17a7dSSiva Chandra Reddy return isa(Def, PublicAPIClass);
6459f17a7dSSiva Chandra Reddy }
6559f17a7dSSiva Chandra Reddy
getTypeAsString(llvm::Record * TypeRecord)6659f17a7dSSiva Chandra Reddy std::string APIIndexer::getTypeAsString(llvm::Record *TypeRecord) {
6759f17a7dSSiva Chandra Reddy if (isaNamedType(TypeRecord) || isaStructType(TypeRecord)) {
6859f17a7dSSiva Chandra Reddy return std::string(TypeRecord->getValueAsString("Name"));
6959f17a7dSSiva Chandra Reddy } else if (isaPtrType(TypeRecord)) {
7059f17a7dSSiva Chandra Reddy return getTypeAsString(TypeRecord->getValueAsDef("PointeeType")) + " *";
7159f17a7dSSiva Chandra Reddy } else if (isaConstType(TypeRecord)) {
7259f17a7dSSiva Chandra Reddy return std::string("const ") +
7359f17a7dSSiva Chandra Reddy getTypeAsString(TypeRecord->getValueAsDef("UnqualifiedType"));
7459f17a7dSSiva Chandra Reddy } else if (isaRestrictedPtrType(TypeRecord)) {
7559f17a7dSSiva Chandra Reddy return getTypeAsString(TypeRecord->getValueAsDef("PointeeType")) +
7659f17a7dSSiva Chandra Reddy " *__restrict";
7759f17a7dSSiva Chandra Reddy } else {
7859f17a7dSSiva Chandra Reddy llvm::PrintFatalError(TypeRecord->getLoc(), "Invalid type.\n");
7959f17a7dSSiva Chandra Reddy }
8059f17a7dSSiva Chandra Reddy }
8159f17a7dSSiva Chandra Reddy
indexStandardSpecDef(llvm::Record * StandardSpec)8259f17a7dSSiva Chandra Reddy void APIIndexer::indexStandardSpecDef(llvm::Record *StandardSpec) {
8359f17a7dSSiva Chandra Reddy auto HeaderSpecList = StandardSpec->getValueAsListOfDefs("Headers");
8459f17a7dSSiva Chandra Reddy for (llvm::Record *HeaderSpec : HeaderSpecList) {
8559f17a7dSSiva Chandra Reddy llvm::StringRef Header = HeaderSpec->getValueAsString("Name");
8659f17a7dSSiva Chandra Reddy if (!StdHeader.hasValue() || Header == StdHeader) {
8759f17a7dSSiva Chandra Reddy PublicHeaders.emplace(Header);
8859f17a7dSSiva Chandra Reddy auto MacroSpecList = HeaderSpec->getValueAsListOfDefs("Macros");
8959f17a7dSSiva Chandra Reddy // TODO: Trigger a fatal error on duplicate specs.
9059f17a7dSSiva Chandra Reddy for (llvm::Record *MacroSpec : MacroSpecList)
9159f17a7dSSiva Chandra Reddy MacroSpecMap[std::string(MacroSpec->getValueAsString("Name"))] =
9259f17a7dSSiva Chandra Reddy MacroSpec;
9359f17a7dSSiva Chandra Reddy
9459f17a7dSSiva Chandra Reddy auto TypeSpecList = HeaderSpec->getValueAsListOfDefs("Types");
9559f17a7dSSiva Chandra Reddy for (llvm::Record *TypeSpec : TypeSpecList)
9659f17a7dSSiva Chandra Reddy TypeSpecMap[std::string(TypeSpec->getValueAsString("Name"))] = TypeSpec;
9759f17a7dSSiva Chandra Reddy
9859f17a7dSSiva Chandra Reddy auto FunctionSpecList = HeaderSpec->getValueAsListOfDefs("Functions");
9959f17a7dSSiva Chandra Reddy for (llvm::Record *FunctionSpec : FunctionSpecList) {
100a32af825SSiva Chandra Reddy auto FunctionName = std::string(FunctionSpec->getValueAsString("Name"));
101a32af825SSiva Chandra Reddy FunctionSpecMap[FunctionName] = FunctionSpec;
102a32af825SSiva Chandra Reddy FunctionToHeaderMap[FunctionName] = std::string(Header);
10359f17a7dSSiva Chandra Reddy }
10459f17a7dSSiva Chandra Reddy
10559f17a7dSSiva Chandra Reddy auto EnumerationSpecList =
10659f17a7dSSiva Chandra Reddy HeaderSpec->getValueAsListOfDefs("Enumerations");
10759f17a7dSSiva Chandra Reddy for (llvm::Record *EnumerationSpec : EnumerationSpecList) {
10859f17a7dSSiva Chandra Reddy EnumerationSpecMap[std::string(
10959f17a7dSSiva Chandra Reddy EnumerationSpec->getValueAsString("Name"))] = EnumerationSpec;
11059f17a7dSSiva Chandra Reddy }
111*9b8ca3c1SSiva Chandra Reddy
112*9b8ca3c1SSiva Chandra Reddy auto ObjectSpecList = HeaderSpec->getValueAsListOfDefs("Objects");
113*9b8ca3c1SSiva Chandra Reddy for (llvm::Record *ObjectSpec : ObjectSpecList) {
114*9b8ca3c1SSiva Chandra Reddy auto ObjectName = std::string(ObjectSpec->getValueAsString("Name"));
115*9b8ca3c1SSiva Chandra Reddy ObjectSpecMap[ObjectName] = ObjectSpec;
116*9b8ca3c1SSiva Chandra Reddy ObjectToHeaderMap[ObjectName] = std::string(Header);
117*9b8ca3c1SSiva Chandra Reddy }
11859f17a7dSSiva Chandra Reddy }
11959f17a7dSSiva Chandra Reddy }
12059f17a7dSSiva Chandra Reddy }
12159f17a7dSSiva Chandra Reddy
indexPublicAPIDef(llvm::Record * PublicAPI)12259f17a7dSSiva Chandra Reddy void APIIndexer::indexPublicAPIDef(llvm::Record *PublicAPI) {
12359f17a7dSSiva Chandra Reddy // While indexing the public API, we do not check if any of the entities
12459f17a7dSSiva Chandra Reddy // requested is from an included standard. Such a check is done while
12559f17a7dSSiva Chandra Reddy // generating the API.
12659f17a7dSSiva Chandra Reddy auto MacroDefList = PublicAPI->getValueAsListOfDefs("Macros");
12759f17a7dSSiva Chandra Reddy for (llvm::Record *MacroDef : MacroDefList)
12859f17a7dSSiva Chandra Reddy MacroDefsMap[std::string(MacroDef->getValueAsString("Name"))] = MacroDef;
12959f17a7dSSiva Chandra Reddy
13059eb542fSSiva Chandra Reddy auto TypeList = PublicAPI->getValueAsListOfStrings("Types");
13159eb542fSSiva Chandra Reddy for (llvm::StringRef TypeName : TypeList)
13259eb542fSSiva Chandra Reddy RequiredTypes.insert(std::string(TypeName));
13359f17a7dSSiva Chandra Reddy
13459f17a7dSSiva Chandra Reddy auto StructList = PublicAPI->getValueAsListOfStrings("Structs");
13559f17a7dSSiva Chandra Reddy for (llvm::StringRef StructName : StructList)
13659f17a7dSSiva Chandra Reddy Structs.insert(std::string(StructName));
13759f17a7dSSiva Chandra Reddy
13859f17a7dSSiva Chandra Reddy auto FunctionList = PublicAPI->getValueAsListOfStrings("Functions");
13959f17a7dSSiva Chandra Reddy for (llvm::StringRef FunctionName : FunctionList)
14059f17a7dSSiva Chandra Reddy Functions.insert(std::string(FunctionName));
14159f17a7dSSiva Chandra Reddy
14259f17a7dSSiva Chandra Reddy auto EnumerationList = PublicAPI->getValueAsListOfStrings("Enumerations");
14359f17a7dSSiva Chandra Reddy for (llvm::StringRef EnumerationName : EnumerationList)
14459f17a7dSSiva Chandra Reddy Enumerations.insert(std::string(EnumerationName));
145*9b8ca3c1SSiva Chandra Reddy
146*9b8ca3c1SSiva Chandra Reddy auto ObjectList = PublicAPI->getValueAsListOfStrings("Objects");
147*9b8ca3c1SSiva Chandra Reddy for (llvm::StringRef ObjectName : ObjectList)
148*9b8ca3c1SSiva Chandra Reddy Objects.insert(std::string(ObjectName));
14959f17a7dSSiva Chandra Reddy }
15059f17a7dSSiva Chandra Reddy
index(llvm::RecordKeeper & Records)15159f17a7dSSiva Chandra Reddy void APIIndexer::index(llvm::RecordKeeper &Records) {
15259f17a7dSSiva Chandra Reddy NamedTypeClass = Records.getClass(NamedTypeClassName);
15359f17a7dSSiva Chandra Reddy PtrTypeClass = Records.getClass(PtrTypeClassName);
15459f17a7dSSiva Chandra Reddy RestrictedPtrTypeClass = Records.getClass(RestrictedPtrTypeClassName);
15559f17a7dSSiva Chandra Reddy StructClass = Records.getClass(StructTypeClassName);
15659f17a7dSSiva Chandra Reddy ConstTypeClass = Records.getClass(ConstTypeClassName);
15759f17a7dSSiva Chandra Reddy StandardSpecClass = Records.getClass(StandardSpecClassName);
15859f17a7dSSiva Chandra Reddy PublicAPIClass = Records.getClass(PublicAPIClassName);
15959f17a7dSSiva Chandra Reddy
16059f17a7dSSiva Chandra Reddy const auto &DefsMap = Records.getDefs();
16159f17a7dSSiva Chandra Reddy for (auto &Pair : DefsMap) {
16259f17a7dSSiva Chandra Reddy llvm::Record *Def = Pair.second.get();
16359f17a7dSSiva Chandra Reddy if (isaStandardSpec(Def))
16459f17a7dSSiva Chandra Reddy indexStandardSpecDef(Def);
16559f17a7dSSiva Chandra Reddy if (isaPublicAPI(Def)) {
16659f17a7dSSiva Chandra Reddy if (!StdHeader.hasValue() ||
16759f17a7dSSiva Chandra Reddy Def->getValueAsString("HeaderName") == StdHeader)
16859f17a7dSSiva Chandra Reddy indexPublicAPIDef(Def);
16959f17a7dSSiva Chandra Reddy }
17059f17a7dSSiva Chandra Reddy }
17159f17a7dSSiva Chandra Reddy }
17259f17a7dSSiva Chandra Reddy
17359f17a7dSSiva Chandra Reddy } // namespace llvm_libc
174