Skip to content

Commit 07b7fc9

Browse files
committed
[apinotes] Add support for C++ methods.
1 parent 545332a commit 07b7fc9

File tree

9 files changed

+258
-3
lines changed

9 files changed

+258
-3
lines changed

clang/include/clang/APINotes/APINotesReader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ class APINotesReader {
184184
/// \returns information about the global function, if known.
185185
VersionedInfo<GlobalFunctionInfo> lookupGlobalFunction(llvm::StringRef name);
186186

187+
VersionedInfo<GlobalFunctionInfo> lookupMemberFunction(llvm::StringRef name);
188+
187189
/// Look for information regarding the given enumerator.
188190
///
189191
/// \param name The name of the enumerator.

clang/include/clang/APINotes/APINotesWriter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ class APINotesWriter {
9393
void addGlobalFunction(llvm::StringRef name, const GlobalFunctionInfo &info,
9494
llvm::VersionTuple swiftVersion);
9595

96+
void addMemberFunction(llvm::StringRef name, const FunctionInfo &info,
97+
llvm::VersionTuple swiftVersion);
98+
9699
/// Add information about an enumerator.
97100
///
98101
/// \param name The name of this enumerator.

clang/lib/APINotes/APINotesFormat.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ enum BlockID {
7272
/// information about the global function.
7373
GLOBAL_FUNCTION_BLOCK_ID,
7474

75+
MEMBER_FUNCTION_BLOCK_ID,
76+
7577
/// The tag data block, which maps tag names to information about
7678
/// the tags.
7779
TAG_BLOCK_ID,
@@ -211,6 +213,16 @@ using GlobalFunctionDataLayout = llvm::BCRecordLayout<
211213
>;
212214
} // namespace global_function_block
213215

216+
namespace member_function_block {
217+
enum { MEMBER_FUNCTION_DATA = 1 };
218+
219+
using MemberFunctionDataLayout = llvm::BCRecordLayout<
220+
MEMBER_FUNCTION_DATA, // record ID
221+
llvm::BCVBR<16>, // table offset within the blob (see below)
222+
llvm::BCBlob // map from name to global function information
223+
>;
224+
} // namespace global_function_block
225+
214226
namespace tag_block {
215227
enum { TAG_DATA = 1 };
216228

clang/lib/APINotes/APINotesReader.cpp

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,24 @@ namespace {
465465
}
466466
};
467467

468+
/// Used to deserialize the on-disk global function table.
469+
class MemberFunctionTableInfo
470+
: public VersionedTableInfo<MemberFunctionTableInfo, unsigned,
471+
GlobalFunctionInfo> {
472+
public:
473+
static internal_key_type ReadKey(const uint8_t *data, unsigned length) {
474+
auto nameID = endian::readNext<uint32_t, little, unaligned>(data);
475+
return nameID;
476+
}
477+
478+
static GlobalFunctionInfo readUnversioned(internal_key_type key,
479+
const uint8_t *&data) {
480+
GlobalFunctionInfo info;
481+
readFunctionInfo(data, info);
482+
return info;
483+
}
484+
};
485+
468486
/// Used to deserialize the on-disk enumerator table.
469487
class EnumConstantTableInfo
470488
: public VersionedTableInfo<EnumConstantTableInfo, unsigned,
@@ -604,6 +622,11 @@ class APINotesReader::Implementation {
604622
/// The global function table.
605623
std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable;
606624

625+
using SerializedMemberFunctionTable =
626+
llvm::OnDiskIterableChainedHashTable<MemberFunctionTableInfo>;
627+
628+
std::unique_ptr<SerializedMemberFunctionTable> MemberFunctionTable;
629+
607630
using SerializedEnumConstantTable =
608631
llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>;
609632

@@ -646,6 +669,8 @@ class APINotesReader::Implementation {
646669
SmallVectorImpl<uint64_t> &scratch);
647670
bool readGlobalFunctionBlock(llvm::BitstreamCursor &cursor,
648671
SmallVectorImpl<uint64_t> &scratch);
672+
bool readMemberFunctionBlock(llvm::BitstreamCursor &cursor,
673+
SmallVectorImpl<uint64_t> &scratch);
649674
bool readEnumConstantBlock(llvm::BitstreamCursor &cursor,
650675
SmallVectorImpl<uint64_t> &scratch);
651676
bool readTagBlock(llvm::BitstreamCursor &cursor,
@@ -1344,6 +1369,84 @@ bool APINotesReader::Implementation::readGlobalFunctionBlock(
13441369
return false;
13451370
}
13461371

1372+
bool APINotesReader::Implementation::readMemberFunctionBlock(
1373+
llvm::BitstreamCursor &cursor,
1374+
SmallVectorImpl<uint64_t> &scratch) {
1375+
if (cursor.EnterSubBlock(MEMBER_FUNCTION_BLOCK_ID))
1376+
return true;
1377+
1378+
llvm::Expected<llvm::BitstreamEntry> maybeNext = cursor.advance();
1379+
if (!maybeNext) {
1380+
// FIXME this drops the error on the floor.
1381+
consumeError(maybeNext.takeError());
1382+
return false;
1383+
}
1384+
llvm::BitstreamEntry next = maybeNext.get();
1385+
while (next.Kind != llvm::BitstreamEntry::EndBlock) {
1386+
if (next.Kind == llvm::BitstreamEntry::Error)
1387+
return true;
1388+
1389+
if (next.Kind == llvm::BitstreamEntry::SubBlock) {
1390+
// Unknown sub-block, possibly for use by a future version of the
1391+
// API notes format.
1392+
if (cursor.SkipBlock())
1393+
return true;
1394+
1395+
maybeNext = cursor.advance();
1396+
if (!maybeNext) {
1397+
// FIXME this drops the error on the floor.
1398+
consumeError(maybeNext.takeError());
1399+
return false;
1400+
}
1401+
next = maybeNext.get();
1402+
continue;
1403+
}
1404+
1405+
scratch.clear();
1406+
StringRef blobData;
1407+
llvm::Expected<unsigned> maybeKind = cursor.readRecord(next.ID, scratch, &blobData);
1408+
if (!maybeKind) {
1409+
// FIXME this drops the error on the floor.
1410+
consumeError(maybeKind.takeError());
1411+
return false;
1412+
}
1413+
unsigned kind = maybeKind.get();
1414+
switch (kind) {
1415+
case member_function_block::MEMBER_FUNCTION_DATA: {
1416+
// Already saw global function table.
1417+
if (MemberFunctionTable)
1418+
return true;
1419+
1420+
uint32_t tableOffset;
1421+
member_function_block::MemberFunctionDataLayout::readRecord(scratch,
1422+
tableOffset);
1423+
auto base = reinterpret_cast<const uint8_t *>(blobData.data());
1424+
1425+
MemberFunctionTable.reset(
1426+
SerializedMemberFunctionTable::Create(base + tableOffset,
1427+
base + sizeof(uint32_t),
1428+
base));
1429+
break;
1430+
}
1431+
1432+
default:
1433+
// Unknown record, possibly for use by a future version of the
1434+
// module format.
1435+
break;
1436+
}
1437+
1438+
maybeNext = cursor.advance();
1439+
if (!maybeNext) {
1440+
// FIXME this drops the error on the floor.
1441+
consumeError(maybeNext.takeError());
1442+
return false;
1443+
}
1444+
next = maybeNext.get();
1445+
}
1446+
1447+
return false;
1448+
}
1449+
13471450
bool APINotesReader::Implementation::readEnumConstantBlock(
13481451
llvm::BitstreamCursor &cursor,
13491452
SmallVectorImpl<uint64_t> &scratch) {
@@ -1697,6 +1800,14 @@ APINotesReader::APINotesReader(llvm::MemoryBuffer *inputBuffer,
16971800
}
16981801
break;
16991802

1803+
case MEMBER_FUNCTION_BLOCK_ID:
1804+
if (!hasValidControlBlock ||
1805+
Impl.readMemberFunctionBlock(cursor, scratch)) {
1806+
failed = true;
1807+
return;
1808+
}
1809+
break;
1810+
17001811
case ENUM_CONSTANT_BLOCK_ID:
17011812
if (!hasValidControlBlock ||
17021813
Impl.readEnumConstantBlock(cursor, scratch)) {
@@ -1952,6 +2063,19 @@ auto APINotesReader::lookupGlobalFunction(StringRef name)
19522063
return { Impl.SwiftVersion, *known };
19532064
}
19542065

2066+
auto APINotesReader::lookupMemberFunction(llvm::StringRef name)
2067+
-> VersionedInfo<GlobalFunctionInfo> {
2068+
Optional<IdentifierID> nameID = Impl.getIdentifier(name);
2069+
if (!nameID)
2070+
return None;
2071+
2072+
auto known = Impl.MemberFunctionTable->find(*nameID);
2073+
if (known == Impl.MemberFunctionTable->end())
2074+
return None;
2075+
2076+
return { Impl.SwiftVersion, *known };
2077+
}
2078+
19552079
auto APINotesReader::lookupEnumConstant(StringRef name)
19562080
-> VersionedInfo<EnumConstantInfo> {
19572081
if (!Impl.EnumConstantTable)

clang/lib/APINotes/APINotesWriter.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ class APINotesWriter::Implementation {
101101
1>>
102102
GlobalFunctions;
103103

104+
llvm::DenseMap<unsigned,
105+
llvm::SmallVector<std::pair<VersionTuple, FunctionInfo>,
106+
1>>
107+
MemberFunctions;
108+
104109
/// Information about enumerators.
105110
///
106111
/// Indexed by the identifier ID.
@@ -169,6 +174,7 @@ class APINotesWriter::Implementation {
169174
void writeObjCSelectorBlock(llvm::BitstreamWriter &writer);
170175
void writeGlobalVariableBlock(llvm::BitstreamWriter &writer);
171176
void writeGlobalFunctionBlock(llvm::BitstreamWriter &writer);
177+
void writeMemberFunctionBlock(llvm::BitstreamWriter &writer);
172178
void writeEnumConstantBlock(llvm::BitstreamWriter &writer);
173179
void writeTagBlock(llvm::BitstreamWriter &writer);
174180
void writeTypedefBlock(llvm::BitstreamWriter &writer);
@@ -970,6 +976,31 @@ namespace {
970976
emitFunctionInfo(out, info);
971977
}
972978
};
979+
980+
/// Used to serialize the on-disk global function table.
981+
class MemberFunctionTableInfo
982+
: public VersionedTableInfo<MemberFunctionTableInfo,
983+
unsigned,
984+
FunctionInfo> {
985+
public:
986+
unsigned getKeyLength(key_type_ref) {
987+
return sizeof(uint32_t);
988+
}
989+
990+
void EmitKey(raw_ostream &out, key_type_ref key, unsigned len) {
991+
endian::Writer writer(out, little);
992+
writer.write<uint32_t>(key);
993+
}
994+
995+
unsigned getUnversionedInfoSize(const FunctionInfo &info) {
996+
return getFunctionInfoSize(info);
997+
}
998+
999+
void emitUnversionedInfo(raw_ostream &out,
1000+
const FunctionInfo &info) {
1001+
emitFunctionInfo(out, info);
1002+
}
1003+
};
9731004
} // end anonymous namespace
9741005

9751006
void APINotesWriter::Implementation::writeGlobalFunctionBlock(
@@ -997,6 +1028,31 @@ void APINotesWriter::Implementation::writeGlobalFunctionBlock(
9971028
layout.emit(ScratchRecord, tableOffset, hashTableBlob);
9981029
}
9991030

1031+
void APINotesWriter::Implementation::writeMemberFunctionBlock(
1032+
llvm::BitstreamWriter &writer) {
1033+
llvm::BCBlockRAII restoreBlock(writer, MEMBER_FUNCTION_BLOCK_ID, 3);
1034+
1035+
if (MemberFunctions.empty())
1036+
return;
1037+
1038+
llvm::SmallString<4096> hashTableBlob;
1039+
uint32_t tableOffset;
1040+
{
1041+
llvm::OnDiskChainedHashTableGenerator<MemberFunctionTableInfo> generator;
1042+
for (auto &entry : MemberFunctions) {
1043+
generator.insert(entry.first, entry.second);
1044+
}
1045+
1046+
llvm::raw_svector_ostream blobStream(hashTableBlob);
1047+
// Make sure that no bucket is at offset 0
1048+
endian::write<uint32_t>(blobStream, 0, little);
1049+
tableOffset = generator.Emit(blobStream);
1050+
}
1051+
1052+
member_function_block::MemberFunctionDataLayout layout(writer);
1053+
layout.emit(ScratchRecord, tableOffset, hashTableBlob);
1054+
}
1055+
10001056
namespace {
10011057
/// Used to serialize the on-disk global enum constant.
10021058
class EnumConstantTableInfo
@@ -1196,6 +1252,7 @@ void APINotesWriter::Implementation::writeToStream(llvm::raw_ostream &os) {
11961252
writeObjCSelectorBlock(writer);
11971253
writeGlobalVariableBlock(writer);
11981254
writeGlobalFunctionBlock(writer);
1255+
writeMemberFunctionBlock(writer);
11991256
writeEnumConstantBlock(writer);
12001257
writeTagBlock(writer);
12011258
writeTypedefBlock(writer);
@@ -1314,6 +1371,13 @@ void APINotesWriter::addGlobalFunction(llvm::StringRef name,
13141371
Impl.GlobalFunctions[nameID].push_back({swiftVersion, info});
13151372
}
13161373

1374+
void APINotesWriter::addMemberFunction(llvm::StringRef name,
1375+
const FunctionInfo &info,
1376+
VersionTuple swiftVersion) {
1377+
IdentifierID nameID = Impl.getIdentifier(name);
1378+
Impl.MemberFunctions[nameID].push_back({swiftVersion, info});
1379+
}
1380+
13171381
void APINotesWriter::addEnumConstant(llvm::StringRef name,
13181382
const EnumConstantInfo &info,
13191383
VersionTuple swiftVersion) {

clang/lib/APINotes/APINotesYAMLCompiler.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,7 @@ struct Tag {
530530
Optional<EnumExtensibilityKind> EnumExtensibility;
531531
Optional<bool> FlagEnum;
532532
Optional<EnumConvenienceAliasKind> EnumConvenienceKind;
533+
FunctionsSeq MemberFuncs;
533534
};
534535

535536
typedef std::vector<Tag> TagsSeq;
@@ -560,6 +561,7 @@ template <> struct MappingTraits<Tag> {
560561
IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
561562
IO.mapOptional("FlagEnum", T.FlagEnum);
562563
IO.mapOptional("EnumKind", T.EnumConvenienceKind);
564+
IO.mapOptional("Methods", T.MemberFuncs);
563565
}
564566
};
565567
} // namespace yaml
@@ -1099,6 +1101,23 @@ namespace {
10991101
}
11001102

11011103
Writer->addTag(t.Name, tagInfo, swiftVersion);
1104+
1105+
for (auto Member : t.MemberFuncs) {
1106+
auto MemberName = (t.Name + "." + Member.Name).str();
1107+
1108+
FunctionInfo info;
1109+
convertAvailability(Member.Availability, info, MemberName);
1110+
info.setSwiftPrivate(Member.SwiftPrivate);
1111+
info.SwiftName = std::string(Member.SwiftName);
1112+
convertParams(Member.Params, info);
1113+
convertNullability(Member.Nullability,
1114+
Member.NullabilityOfRet,
1115+
info, MemberName);
1116+
info.ResultType = std::string(Member.ResultType);
1117+
info.setRetainCountConvention(Member.RetainCountConvention);
1118+
1119+
Writer->addMemberFunction(MemberName, info, swiftVersion);
1120+
}
11021121
}
11031122

11041123
// Write all typedefs.

0 commit comments

Comments
 (0)