[cfe-commits] r69884 - in /cfe/trunk: include/clang/Basic/IdentifierTable.h include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHReader.h include/clang/Frontend/PCHWriter.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp test/PCH/objc_exprs.h test/PCH/objc_exprs.m
Steve Naroff
snaroff at apple.com
Thu Apr 23 03:40:11 PDT 2009
Author: snaroff
Date: Thu Apr 23 05:39:46 2009
New Revision: 69884
URL: http://llvm.org/viewvc/llvm-project?rev=69884&view=rev
Log:
Add PCH read/write support for Objective-C Selectors.
Note: This support is non-lazy. Once we get "Cocoa.h" humming, we can optimize this.
Modified:
cfe/trunk/include/clang/Basic/IdentifierTable.h
cfe/trunk/include/clang/Frontend/PCHBitCodes.h
cfe/trunk/include/clang/Frontend/PCHReader.h
cfe/trunk/include/clang/Frontend/PCHWriter.h
cfe/trunk/lib/Frontend/PCHReader.cpp
cfe/trunk/lib/Frontend/PCHWriter.cpp
cfe/trunk/test/PCH/objc_exprs.h
cfe/trunk/test/PCH/objc_exprs.m
Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=69884&r1=69883&r2=69884&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Thu Apr 23 05:39:46 2009
@@ -370,7 +370,6 @@
InfoPtr = reinterpret_cast<uintptr_t>(SI);
assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
}
- Selector(uintptr_t V) : InfoPtr(V) {}
IdentifierInfo *getAsIdentifierInfo() const {
if (getIdentifierInfoFlag())
@@ -388,6 +387,7 @@
/// The default ctor should only be used when creating data structures that
/// will contain selectors.
Selector() : InfoPtr(0) {}
+ Selector(uintptr_t V) : InfoPtr(V) {}
/// operator==/!= - Indicate whether the specified selectors are identical.
bool operator==(Selector RHS) const {
Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=69884&r1=69883&r2=69884&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Thu Apr 23 05:39:46 2009
@@ -45,6 +45,8 @@
/// file.
typedef uint32_t IdentID;
+ typedef uint32_t SelectorID;
+
/// \brief Describes the various kinds of blocks that occur within
/// a PCH file.
enum BlockIDs {
@@ -66,7 +68,10 @@
/// \brief The block containing the definitions of all of the
/// declarations stored in the PCH file.
- DECLS_BLOCK_ID
+ DECLS_BLOCK_ID,
+
+ /// \brief The block containing ObjC selectors stored in the PCH file.
+ SELECTOR_BLOCK_ID
};
/// \brief Record types that occur within the PCH block itself.
@@ -160,7 +165,10 @@
/// \brief Record code for the array of locally-scoped external
/// declarations.
- LOCALLY_SCOPED_EXTERNAL_DECLS = 11
+ LOCALLY_SCOPED_EXTERNAL_DECLS = 11,
+
+ /// \brief Record code for the Objective-C Selector Table.
+ SELECTOR_TABLE = 12
};
/// \brief Record types used within a source manager block.
Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=69884&r1=69883&r2=69884&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Thu Apr 23 05:39:46 2009
@@ -145,6 +145,9 @@
/// an IdentifierInfo* that has already been resolved.
llvm::SmallVector<uint64_t, 16> IdentifierData;
+ /// \brief SelectorData, indexed by the selector ID minus one.
+ llvm::SmallVector<Selector, 16> SelectorData;
+
/// \brief The set of external definitions stored in the the PCH
/// file.
llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
@@ -198,13 +201,15 @@
/// \brief FIXME: document!
llvm::SmallVector<uint64_t, 4> SpecialTypes;
- PCHReadResult ReadPCHBlock(uint64_t &PreprocessorBlockOffset);
+ PCHReadResult ReadPCHBlock(uint64_t &PreprocessorBlockOffset,
+ uint64_t &SelectorBlockOffset);
bool CheckPredefinesBuffer(const char *PCHPredef,
unsigned PCHPredefLen,
FileID PCHBufferID);
PCHReadResult ReadSourceManagerBlock();
bool ReadPreprocessorBlock();
-
+ bool ReadSelectorBlock();
+
bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record);
QualType ReadTypeRecord(uint64_t Offset);
void LoadedDecl(unsigned Index, Decl *D);
@@ -313,6 +318,12 @@
IdentifierInfo *GetIdentifierInfo(const RecordData &Record, unsigned &Idx) {
return DecodeIdentifierInfo(Record[Idx++]);
}
+
+ Selector DecodeSelector(unsigned Idx);
+
+ Selector GetSelector(const RecordData &Record, unsigned &Idx) {
+ return DecodeSelector(Record[Idx++]);
+ }
DeclarationName ReadDeclarationName(const RecordData &Record, unsigned &Idx);
/// \brief Read an integral value
Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=69884&r1=69883&r2=69884&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Thu Apr 23 05:39:46 2009
@@ -93,11 +93,17 @@
/// discovery), starting at 1. An ID of zero refers to a NULL
/// IdentifierInfo.
llvm::DenseMap<const IdentifierInfo *, pch::IdentID> IdentifierIDs;
-
+
/// \brief Offsets of each of the identifier IDs into the identifier
/// table, shifted left by one bit with the low bit set.
llvm::SmallVector<uint64_t, 16> IdentifierOffsets;
+ /// \brief Map that provides the ID numbers of each Selector.
+ llvm::DenseMap<Selector, pch::SelectorID> SelectorIDs;
+
+ /// \brief A vector of all Selectors (ordered by ID).
+ llvm::SmallVector<Selector, 16> SelVector;
+
/// \brief Offsets of each of the macro identifiers into the
/// bitstream.
///
@@ -154,6 +160,7 @@
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
void WriteDeclsBlock(ASTContext &Context);
void WriteIdentifierTable(Preprocessor &PP);
+ void WriteSelectorTable();
void WriteAttributeRecord(const Attr *Attr);
public:
@@ -179,6 +186,9 @@
/// \brief Emit a reference to an identifier
void AddIdentifierRef(const IdentifierInfo *II, RecordData &Record);
+ /// \brief Emit a Selector (which is a smart pointer reference)
+ void AddSelectorRef(const Selector, RecordData &Record);
+
/// \brief Get the unique number used to refer to the given
/// identifier.
pch::IdentID getIdentifierRef(const IdentifierInfo *II);
Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=69884&r1=69883&r2=69884&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Thu Apr 23 05:39:46 2009
@@ -1063,7 +1063,7 @@
unsigned PCHStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
VisitExpr(E);
- // FIXME: Selectors.
+ E->setSelector(Reader.GetSelector(Record, Idx));
E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
return 0;
@@ -1586,8 +1586,69 @@
}
}
+bool PCHReader::ReadSelectorBlock() {
+ if (Stream.EnterSubBlock(pch::SELECTOR_BLOCK_ID))
+ return Error("Malformed selector block record");
+
+ RecordData Record;
+ while (true) {
+ unsigned Code = Stream.ReadCode();
+ switch (Code) {
+ case llvm::bitc::END_BLOCK:
+ if (Stream.ReadBlockEnd())
+ return Error("Error at end of preprocessor block");
+ return false;
+
+ case llvm::bitc::ENTER_SUBBLOCK:
+ // No known subblocks, always skip them.
+ Stream.ReadSubBlockID();
+ if (Stream.SkipBlock())
+ return Error("Malformed block record");
+ continue;
+
+ case llvm::bitc::DEFINE_ABBREV:
+ Stream.ReadAbbrevRecord();
+ continue;
+ default: break;
+ }
+
+ // Read a record.
+ Record.clear();
+ pch::PCHRecordTypes RecType =
+ (pch::PCHRecordTypes)Stream.ReadRecord(Code, Record);
+ switch (RecType) {
+ default: // Default behavior: ignore unknown records.
+ break;
+ case pch::SELECTOR_TABLE:
+ unsigned Idx = 1; // Record[0] == pch::SELECTOR_TABLE.
+ unsigned NumSels = Record[Idx++];
+
+ llvm::SmallVector<IdentifierInfo *, 8> KeyIdents;
+ for (unsigned SelIdx = 0; SelIdx < NumSels; SelIdx++) {
+ unsigned NumArgs = Record[Idx++];
+ KeyIdents.clear();
+ if (NumArgs <= 1) {
+ IdentifierInfo *II = DecodeIdentifierInfo(Record[Idx++]);
+ assert(II && "DecodeIdentifierInfo returned 0");
+ KeyIdents.push_back(II);
+ } else {
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ IdentifierInfo *II = DecodeIdentifierInfo(Record[Idx++]);
+ assert(II && "DecodeIdentifierInfo returned 0");
+ KeyIdents.push_back(II);
+ }
+ }
+ Selector Sel = PP.getSelectorTable().getSelector(NumArgs,&KeyIdents[0]);
+ SelectorData.push_back(Sel);
+ }
+ }
+ }
+ return false;
+}
+
PCHReader::PCHReadResult
-PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) {
+PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset,
+ uint64_t &SelectorBlockOffset) {
if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
Error("Malformed block record");
return Failure;
@@ -1630,6 +1691,20 @@
return Failure;
}
break;
+
+ case pch::SELECTOR_BLOCK_ID:
+ // Skip the selector block for now, but remember where it is. We
+ // want to read it in after the identifier table.
+ if (SelectorBlockOffset) {
+ Error("Multiple selector blocks found.");
+ return Failure;
+ }
+ SelectorBlockOffset = Stream.GetCurrentBitNo();
+ if (Stream.SkipBlock()) {
+ Error("Malformed block record");
+ return Failure;
+ }
+ break;
case pch::SOURCE_MANAGER_BLOCK_ID:
switch (ReadSourceManagerBlock()) {
@@ -1740,7 +1815,6 @@
TotalLexicalDeclContexts = Record[2];
TotalVisibleDeclContexts = Record[3];
break;
-
case pch::TENTATIVE_DEFINITIONS:
if (!TentativeDefinitions.empty()) {
Error("Duplicate TENTATIVE_DEFINITIONS record in PCH file");
@@ -1758,7 +1832,6 @@
break;
}
}
-
Error("Premature end of bitstream");
return Failure;
}
@@ -1791,6 +1864,8 @@
// We expect a number of well-defined blocks, though we don't necessarily
// need to understand them all.
uint64_t PreprocessorBlockOffset = 0;
+ uint64_t SelectorBlockOffset = 0;
+
while (!Stream.AtEndOfStream()) {
unsigned Code = Stream.ReadCode();
@@ -1810,7 +1885,7 @@
}
break;
case pch::PCH_BLOCK_ID:
- switch (ReadPCHBlock(PreprocessorBlockOffset)) {
+ switch (ReadPCHBlock(PreprocessorBlockOffset, SelectorBlockOffset)) {
case Success:
break;
@@ -1882,6 +1957,14 @@
return Failure;
}
}
+ if (SelectorBlockOffset) {
+ SavedStreamPosition SavedPos(Stream);
+ Stream.JumpToBit(SelectorBlockOffset);
+ if (ReadSelectorBlock()) {
+ Error("Malformed preprocessor block");
+ return Failure;
+ }
+ }
return Success;
}
@@ -2633,6 +2716,22 @@
return reinterpret_cast<IdentifierInfo *>(IdentifierData[ID - 1]);
}
+Selector PCHReader::DecodeSelector(unsigned ID) {
+ if (ID == 0)
+ return Selector();
+
+ if (SelectorData.empty()) {
+ Error("No selector table in PCH file");
+ return Selector();
+ }
+
+ if (ID > SelectorData.size()) {
+ Error("Selector ID out of range");
+ return Selector();
+ }
+ return SelectorData[ID-1];
+}
+
DeclarationName
PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=69884&r1=69883&r2=69884&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Thu Apr 23 05:39:46 2009
@@ -1182,9 +1182,7 @@
void PCHStmtWriter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
VisitExpr(E);
- assert(0 && "Can't write a selector yet!");
- // FIXME! Write selectors.
- //Writer.WriteSubStmt(E->getSelector());
+ Writer.AddSelectorRef(E->getSelector(), Record);
Writer.AddSourceLocation(E->getAtLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
Code = pch::EXPR_OBJC_SELECTOR_EXPR;
@@ -1888,6 +1886,26 @@
Stream.EmitRecord(pch::IDENTIFIER_OFFSET, IdentifierOffsets);
}
+void PCHWriter::WriteSelectorTable() {
+ Stream.EnterSubblock(pch::SELECTOR_BLOCK_ID, 3);
+ RecordData Record;
+ Record.push_back(pch::SELECTOR_TABLE);
+ Record.push_back(SelectorIDs.size());
+
+ // Create the on-disk representation.
+ for (unsigned selIdx = 0; selIdx < SelVector.size(); selIdx++) {
+ assert(SelVector[selIdx].getAsOpaquePtr() && "NULL Selector found");
+ Record.push_back(SelVector[selIdx].getNumArgs());
+ if (SelVector[selIdx].getNumArgs())
+ for (unsigned i = 0; i < SelVector[selIdx].getNumArgs(); i++)
+ AddIdentifierRef(SelVector[selIdx].getIdentifierInfoForSlot(i), Record);
+ else
+ AddIdentifierRef(SelVector[selIdx].getIdentifierInfoForSlot(0), Record);
+ }
+ Stream.EmitRecord(pch::SELECTOR_TABLE, Record);
+ Stream.ExitBlock();
+}
+
/// \brief Write a record containing the given attributes.
void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
RecordData Record;
@@ -2078,6 +2096,7 @@
WritePreprocessor(PP);
WriteTypesBlock(Context);
WriteDeclsBlock(Context);
+ WriteSelectorTable();
WriteIdentifierTable(PP);
Stream.EmitRecord(pch::TYPE_OFFSET, TypeOffsets);
Stream.EmitRecord(pch::DECL_OFFSET, DeclOffsets);
@@ -2145,6 +2164,20 @@
return ID;
}
+void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
+ if (SelRef.getAsOpaquePtr() == 0) {
+ Record.push_back(0);
+ return;
+ }
+
+ pch::SelectorID &SID = SelectorIDs[SelRef];
+ if (SID == 0) {
+ SID = SelectorIDs.size();
+ SelVector.push_back(SelRef);
+ }
+ Record.push_back(SID);
+}
+
void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
if (T.isNull()) {
Record.push_back(pch::PREDEF_TYPE_NULL_ID);
@@ -2223,7 +2256,7 @@
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
- assert(false && "Serialization of Objective-C selectors unavailable");
+ AddSelectorRef(Name.getObjCSelector(), Record);
break;
case DeclarationName::CXXConstructorName:
Modified: cfe/trunk/test/PCH/objc_exprs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/objc_exprs.h?rev=69884&r1=69883&r2=69884&view=diff
==============================================================================
--- cfe/trunk/test/PCH/objc_exprs.h (original)
+++ cfe/trunk/test/PCH/objc_exprs.h Thu Apr 23 05:39:46 2009
@@ -6,6 +6,9 @@
typedef typeof(@"foo" "bar") objc_string;
typedef typeof(@encode(int)) objc_encode;
typedef typeof(@protocol(foo)) objc_protocol;
+typedef typeof(@selector(noArgs)) objc_selector_noArgs;
+typedef typeof(@selector(oneArg:)) objc_selector_oneArg;
+typedef typeof(@selector(foo:bar:)) objc_selector_twoArg;
// Types.
Modified: cfe/trunk/test/PCH/objc_exprs.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/objc_exprs.m?rev=69884&r1=69883&r2=69884&view=diff
==============================================================================
--- cfe/trunk/test/PCH/objc_exprs.m (original)
+++ cfe/trunk/test/PCH/objc_exprs.m Thu Apr 23 05:39:46 2009
@@ -21,3 +21,8 @@
int *T1 = (objc_interface_ty)0; // expected-warning {{aka 'itf *'}}
int *T2 = (objc_qual_interface_ty)0; // expected-warning {{aka 'itf<foo> *'}}
+objc_selector_noArgs s1;
+objc_selector_oneArg s2;
+objc_selector_twoArg s3;
+
+
More information about the cfe-commits
mailing list