//===--- ModuleFile.cpp - Loading a serialized module -----------*- c++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "ModuleFile.h" #include "ModuleFormat.h" #include "llvm/Support/MemoryBuffer.h" using namespace swift; ModuleFile::ModuleFile(llvm::OwningPtr &&input) : InputFile(std::move(input)), InputReader(reinterpret_cast(InputFile->getBufferStart()), reinterpret_cast(InputFile->getBufferEnd())), Status(ModuleStatus::FallBackToTranslationUnit) { llvm::BitstreamCursor cursor{InputReader}; using namespace serialization; for (unsigned char byte : SIGNATURE) { if (cursor.AtEndOfStream() || cursor.Read(8) != byte) return error(); } // Future-proofing: make sure we validate the control block before we try to // read any other blocks. bool hasValidControlBlock = false; SmallVector scratch; auto topLevelEntry = cursor.advance(); while (topLevelEntry.Kind == llvm::BitstreamEntry::SubBlock) { switch (topLevelEntry.ID) { case llvm::bitc::BLOCKINFO_BLOCK_ID: if (cursor.ReadBlockInfoBlock()) return error(); break; case CONTROL_BLOCK_ID: // FIXME: Actually validate the control block. if (cursor.SkipBlock()) return error(); hasValidControlBlock = true; break; case INPUT_BLOCK_ID: { if (!hasValidControlBlock) return error(); cursor.EnterSubBlock(INPUT_BLOCK_ID); auto next = cursor.advance(); while (next.Kind == llvm::BitstreamEntry::Record) { scratch.clear(); StringRef blobData; unsigned kind = cursor.readRecord(next.ID, scratch, &blobData); switch (kind) { case input_block::SOURCE_FILE: assert(scratch.empty()); SourcePaths.push_back(blobData); break; default: // Unknown input kind, possibly for use by a future version of the // module format. // FIXME: Should we warn about this? break; } next = cursor.advance(); } if (next.Kind != llvm::BitstreamEntry::EndBlock) return error(); break; } default: // Unknown top-level block, possibly for use by a future version of the // module format. if (cursor.SkipBlock()) return error(); break; } topLevelEntry = cursor.advance(llvm::BitstreamCursor::AF_DontPopBlockAtEnd); } if (topLevelEntry.Kind != llvm::BitstreamEntry::EndBlock) return error(); }