summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
diff options
context:
space:
mode:
authorMehdi Amini <mehdi.amini@apple.com>2016-07-11 23:10:18 +0000
committerMehdi Amini <mehdi.amini@apple.com>2016-07-11 23:10:18 +0000
commite75aa6f674ce90570fba9e5a3600535cba12a016 (patch)
tree8f2b3cbf8ccbda75c65ceaa416d8c99ca2061acc /llvm/lib/Bitcode/Reader/BitcodeReader.cpp
parentc9c5405b52dd8063c4a2253f1824bcaf519a39ca (diff)
downloadbcm5719-llvm-e75aa6f674ce90570fba9e5a3600535cba12a016.tar.gz
bcm5719-llvm-e75aa6f674ce90570fba9e5a3600535cba12a016.zip
Add a libLTO API to query a memory buffer and check if it contains ObjC categories
The linker supports a feature to force load an object from a static archive if it defines an Objective-C category. This API supports this feature by looking at every section in the module to find if a category is defined in the module. llvm-svn: 275125
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 9aaf3500cad..73a30c61eca 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -313,6 +313,10 @@ public:
/// Cheap mechanism to just extract the identification block out of bitcode.
ErrorOr<std::string> parseIdentificationBlock();
+ /// Peak at the module content and return true if any ObjC category or class
+ /// is found.
+ ErrorOr<bool> hasObjCCategory();
+
static uint64_t decodeSignRotatedValue(uint64_t V);
/// Materialize any deferred Metadata block.
@@ -450,6 +454,7 @@ private:
ArrayRef<uint64_t> Record);
std::error_code parseMetadataAttachment(Function &F);
ErrorOr<std::string> parseModuleTriple();
+ ErrorOr<bool> hasObjCCategoryInModule();
std::error_code parseUseLists();
std::error_code initStream(std::unique_ptr<DataStreamer> Streamer);
std::error_code initStreamFromBuffer();
@@ -4195,6 +4200,81 @@ std::error_code BitcodeReader::parseGlobalObjectAttachment(
return std::error_code();
}
+ErrorOr<bool> BitcodeReader::hasObjCCategory() {
+ if (std::error_code EC = initStream(nullptr))
+ return EC;
+
+ // Sniff for the signature.
+ if (!hasValidBitcodeHeader(Stream))
+ return error("Invalid bitcode signature");
+
+ // We expect a number of well-defined blocks, though we don't necessarily
+ // need to understand them all.
+ while (1) {
+ BitstreamEntry Entry = Stream.advance();
+
+ switch (Entry.Kind) {
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ return std::error_code();
+
+ case BitstreamEntry::SubBlock:
+ if (Entry.ID == bitc::MODULE_BLOCK_ID)
+ return hasObjCCategoryInModule();
+
+ // Ignore other sub-blocks.
+ if (Stream.SkipBlock())
+ return error("Malformed block");
+ continue;
+
+ case BitstreamEntry::Record:
+ Stream.skipRecord(Entry.ID);
+ continue;
+ }
+ }
+}
+
+ErrorOr<bool> BitcodeReader::hasObjCCategoryInModule() {
+ if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+ return error("Invalid record");
+
+ SmallVector<uint64_t, 64> Record;
+ // Read all the records for this module.
+ while (1) {
+ BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case BitstreamEntry::SubBlock: // Handled for us already.
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ return false;
+ case BitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ switch (Stream.readRecord(Entry.ID, Record)) {
+ default:
+ break; // Default behavior, ignore unknown content.
+ case bitc::MODULE_CODE_SECTIONNAME: { // SECTIONNAME: [strchr x N]
+ std::string S;
+ if (convertToString(Record, 0, S))
+ return error("Invalid record");
+ // Check for the i386 and other (x86_64, ARM) conventions
+ if (S.find("__DATA, __objc_catlist") != std::string::npos ||
+ S.find("__OBJC,__category") != std::string::npos)
+ return true;
+ break;
+ }
+ }
+ Record.clear();
+ }
+ llvm_unreachable("Exit infinite loop");
+}
+
/// Parse metadata attachments.
std::error_code BitcodeReader::parseMetadataAttachment(Function &F) {
if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
@@ -6548,6 +6628,16 @@ std::string llvm::getBitcodeTargetTriple(MemoryBufferRef Buffer,
return Triple.get();
}
+bool llvm::isBitcodeContainingObjCCategory(MemoryBufferRef Buffer,
+ LLVMContext &Context) {
+ std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
+ auto R = llvm::make_unique<BitcodeReader>(Buf.release(), Context);
+ ErrorOr<bool> hasObjCCategory = R->hasObjCCategory();
+ if (hasObjCCategory.getError())
+ return false;
+ return hasObjCCategory.get();
+}
+
std::string llvm::getBitcodeProducerString(MemoryBufferRef Buffer,
LLVMContext &Context) {
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
OpenPOWER on IntegriCloud