BitStream reader: propagate errors
The bitstream reader handles errors poorly. This has two effects: * Bugs in file handling (especially modules) manifest as an "unexpected end of file" crash * Users of clang as a library end up aborting because the code unconditionally calls `report_fatal_error` The bitstream reader should be more resilient and return Expected / Error as soon as an error is encountered, not way late like it does now. This patch starts doing so and adopting the error handling where I think it makes sense. There's plenty more to do: this patch propagates errors to be minimally useful, and follow-ups will propagate them further and improve diagnostics. https://bugs.llvm.org/show_bug.cgi?id=42311 <rdar://problem/33159405> Differential Revision: https://reviews.llvm.org/D63518 llvm-svn: 364464
This commit is contained in:
parent
afa58b6ba1
commit
0e82895826
|
@ -491,24 +491,27 @@ template <typename T>
|
|||
llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
|
||||
Record R;
|
||||
llvm::StringRef Blob;
|
||||
unsigned RecID = Stream.readRecord(ID, R, &Blob);
|
||||
return parseRecord(R, RecID, Blob, I);
|
||||
llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
|
||||
if (!MaybeRecID)
|
||||
return MaybeRecID.takeError();
|
||||
return parseRecord(R, MaybeRecID.get(), Blob, I);
|
||||
}
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
|
||||
Record R;
|
||||
llvm::StringRef Blob;
|
||||
unsigned RecID = Stream.readRecord(ID, R, &Blob);
|
||||
return parseRecord(R, RecID, Blob, I, CurrentReferenceField);
|
||||
llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
|
||||
if (!MaybeRecID)
|
||||
return MaybeRecID.takeError();
|
||||
return parseRecord(R, MaybeRecID.get(), Blob, I, CurrentReferenceField);
|
||||
}
|
||||
|
||||
// Read a block of records into a single info.
|
||||
template <typename T>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
|
||||
if (Stream.EnterSubBlock(ID))
|
||||
return llvm::make_error<llvm::StringError>("Unable to enter subblock.\n",
|
||||
llvm::inconvertibleErrorCode());
|
||||
if (llvm::Error Err = Stream.EnterSubBlock(ID))
|
||||
return Err;
|
||||
|
||||
while (true) {
|
||||
unsigned BlockOrCode = 0;
|
||||
|
@ -521,9 +524,9 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
|
|||
case Cursor::BlockEnd:
|
||||
return llvm::Error::success();
|
||||
case Cursor::BlockBegin:
|
||||
if (auto Err = readSubBlock(BlockOrCode, I)) {
|
||||
if (!Stream.SkipBlock())
|
||||
continue;
|
||||
if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {
|
||||
if (llvm::Error Skipped = Stream.SkipBlock())
|
||||
return joinErrors(std::move(Err), std::move(Skipped));
|
||||
return Err;
|
||||
}
|
||||
continue;
|
||||
|
@ -605,18 +608,34 @@ ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
|
|||
BlockOrRecordID = 0;
|
||||
|
||||
while (!Stream.AtEndOfStream()) {
|
||||
unsigned Code = Stream.ReadCode();
|
||||
Expected<unsigned> MaybeCode = Stream.ReadCode();
|
||||
if (!MaybeCode) {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(MaybeCode.takeError());
|
||||
return Cursor::BadBlock;
|
||||
}
|
||||
|
||||
switch ((llvm::bitc::FixedAbbrevIDs)Code) {
|
||||
// FIXME check that the enum is in range.
|
||||
auto Code = static_cast<llvm::bitc::FixedAbbrevIDs>(MaybeCode.get());
|
||||
|
||||
switch (Code) {
|
||||
case llvm::bitc::ENTER_SUBBLOCK:
|
||||
BlockOrRecordID = Stream.ReadSubBlockID();
|
||||
if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID())
|
||||
BlockOrRecordID = MaybeID.get();
|
||||
else {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(MaybeID.takeError());
|
||||
}
|
||||
return Cursor::BlockBegin;
|
||||
case llvm::bitc::END_BLOCK:
|
||||
if (Stream.ReadBlockEnd())
|
||||
return Cursor::BadBlock;
|
||||
return Cursor::BlockEnd;
|
||||
case llvm::bitc::DEFINE_ABBREV:
|
||||
Stream.ReadAbbrevRecord();
|
||||
if (llvm::Error Err = Stream.ReadAbbrevRecord()) {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(std::move(Err));
|
||||
}
|
||||
continue;
|
||||
case llvm::bitc::UNABBREV_RECORD:
|
||||
return Cursor::BadBlock;
|
||||
|
@ -634,17 +653,24 @@ llvm::Error ClangDocBitcodeReader::validateStream() {
|
|||
llvm::inconvertibleErrorCode());
|
||||
|
||||
// Sniff for the signature.
|
||||
if (Stream.Read(8) != BitCodeConstants::Signature[0] ||
|
||||
Stream.Read(8) != BitCodeConstants::Signature[1] ||
|
||||
Stream.Read(8) != BitCodeConstants::Signature[2] ||
|
||||
Stream.Read(8) != BitCodeConstants::Signature[3])
|
||||
return llvm::make_error<llvm::StringError>("Invalid bitcode signature.\n",
|
||||
llvm::inconvertibleErrorCode());
|
||||
for (int Idx = 0; Idx != 4; ++Idx) {
|
||||
Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8);
|
||||
if (!MaybeRead)
|
||||
return MaybeRead.takeError();
|
||||
else if (MaybeRead.get() != BitCodeConstants::Signature[Idx])
|
||||
return llvm::make_error<llvm::StringError>(
|
||||
"Invalid bitcode signature.\n", llvm::inconvertibleErrorCode());
|
||||
}
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
|
||||
BlockInfo = Stream.ReadBlockInfoBlock();
|
||||
Expected<Optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
|
||||
Stream.ReadBlockInfoBlock();
|
||||
if (!MaybeBlockInfo)
|
||||
return MaybeBlockInfo.takeError();
|
||||
else
|
||||
BlockInfo = MaybeBlockInfo.get();
|
||||
if (!BlockInfo)
|
||||
return llvm::make_error<llvm::StringError>(
|
||||
"Unable to parse BlockInfoBlock.\n", llvm::inconvertibleErrorCode());
|
||||
|
@ -687,11 +713,16 @@ ClangDocBitcodeReader::readBitcode() {
|
|||
|
||||
// Read the top level blocks.
|
||||
while (!Stream.AtEndOfStream()) {
|
||||
unsigned Code = Stream.ReadCode();
|
||||
if (Code != llvm::bitc::ENTER_SUBBLOCK)
|
||||
Expected<unsigned> MaybeCode = Stream.ReadCode();
|
||||
if (!MaybeCode)
|
||||
return MaybeCode.takeError();
|
||||
if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK)
|
||||
return llvm::make_error<llvm::StringError>(
|
||||
"No blocks in input.\n", llvm::inconvertibleErrorCode());
|
||||
unsigned ID = Stream.ReadSubBlockID();
|
||||
Expected<unsigned> MaybeID = Stream.ReadSubBlockID();
|
||||
if (!MaybeID)
|
||||
return MaybeID.takeError();
|
||||
unsigned ID = MaybeID.get();
|
||||
switch (ID) {
|
||||
// NamedType and Comment blocks should not appear at the top level
|
||||
case BI_TYPE_BLOCK_ID:
|
||||
|
@ -720,8 +751,11 @@ ClangDocBitcodeReader::readBitcode() {
|
|||
return std::move(Err);
|
||||
continue;
|
||||
default:
|
||||
if (!Stream.SkipBlock())
|
||||
continue;
|
||||
if (llvm::Error Err = Stream.SkipBlock()) {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(std::move(Err));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return std::move(Infos);
|
||||
|
|
|
@ -214,7 +214,7 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
|
|||
|
||||
// AbbreviationMap
|
||||
|
||||
constexpr char BitCodeConstants::Signature[];
|
||||
constexpr unsigned char BitCodeConstants::Signature[];
|
||||
|
||||
void ClangDocBitcodeWriter::AbbreviationMap::add(RecordId RID,
|
||||
unsigned AbbrevID) {
|
||||
|
|
|
@ -44,7 +44,7 @@ struct BitCodeConstants {
|
|||
static constexpr unsigned ReferenceTypeSize = 8U;
|
||||
static constexpr unsigned USRLengthSize = 6U;
|
||||
static constexpr unsigned USRBitLengthSize = 8U;
|
||||
static constexpr char Signature[4] = {'D', 'O', 'C', 'S'};
|
||||
static constexpr unsigned char Signature[4] = {'D', 'O', 'C', 'S'};
|
||||
static constexpr int USRHashSize = 20;
|
||||
};
|
||||
|
||||
|
|
|
@ -422,8 +422,9 @@ ParsedAST::build(std::unique_ptr<CompilerInvocation> CI,
|
|||
// Collect tokens of the main file.
|
||||
syntax::TokenCollector Tokens(Clang->getPreprocessor());
|
||||
|
||||
if (!Action->Execute())
|
||||
log("Execute() failed when building AST for {0}", MainInput.getFile());
|
||||
if (llvm::Error Err = Action->Execute())
|
||||
log("Execute() failed when building AST for {0}: {1}", MainInput.getFile(),
|
||||
toString(std::move(Err)));
|
||||
|
||||
std::vector<Decl *> ParsedDecls = Action->takeTopLevelDecls();
|
||||
// AST traversals should exclude the preamble, to avoid performance cliffs.
|
||||
|
|
|
@ -1105,8 +1105,9 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
|
|||
if (Includes)
|
||||
Clang->getPreprocessor().addPPCallbacks(
|
||||
collectIncludeStructureCallback(Clang->getSourceManager(), Includes));
|
||||
if (!Action.Execute()) {
|
||||
log("Execute() failed when running codeComplete for {0}", Input.FileName);
|
||||
if (llvm::Error Err = Action.Execute()) {
|
||||
log("Execute() failed when running codeComplete for {0}: {1}",
|
||||
Input.FileName, toString(std::move(Err)));
|
||||
return false;
|
||||
}
|
||||
Action.EndSourceFile();
|
||||
|
|
|
@ -456,9 +456,9 @@ llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd,
|
|||
if (!Action->BeginSourceFile(*Clang, Input))
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"BeginSourceFile() failed");
|
||||
if (!Action->Execute())
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"Execute() failed");
|
||||
if (llvm::Error Err = Action->Execute())
|
||||
return Err;
|
||||
|
||||
Action->EndSourceFile();
|
||||
if (Clang->hasDiagnostics() &&
|
||||
Clang->getDiagnostics().hasUncompilableErrorOccurred()) {
|
||||
|
|
|
@ -68,7 +68,7 @@ protected:
|
|||
IncludeStructure Includes;
|
||||
Clang->getPreprocessor().addPPCallbacks(
|
||||
collectIncludeStructureCallback(Clang->getSourceManager(), &Includes));
|
||||
EXPECT_TRUE(Action.Execute());
|
||||
EXPECT_FALSE(Action.Execute());
|
||||
Action.EndSourceFile();
|
||||
return Includes;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
@ -1303,6 +1304,12 @@ inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
|
|||
return DiagnosticBuilder(this);
|
||||
}
|
||||
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
llvm::Error &&E) {
|
||||
DB.AddString(toString(std::move(E)));
|
||||
return DB;
|
||||
}
|
||||
|
||||
inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {
|
||||
return Report(SourceLocation(), DiagID);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "clang/Frontend/ASTUnit.h"
|
||||
#include "clang/Frontend/FrontendOptions.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -229,7 +230,7 @@ public:
|
|||
bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input);
|
||||
|
||||
/// Set the source manager's main input file, and run the action.
|
||||
bool Execute();
|
||||
llvm::Error Execute();
|
||||
|
||||
/// Perform any per-file post processing, deallocate per-file
|
||||
/// objects, and run statistics and output file cleanup code.
|
||||
|
|
|
@ -1437,6 +1437,7 @@ private:
|
|||
void Error(StringRef Msg) const;
|
||||
void Error(unsigned DiagID, StringRef Arg1 = StringRef(),
|
||||
StringRef Arg2 = StringRef()) const;
|
||||
void Error(llvm::Error &&Err) const;
|
||||
|
||||
public:
|
||||
/// Load the AST file and validate its contents against the given
|
||||
|
@ -2379,7 +2380,8 @@ public:
|
|||
|
||||
/// Reads a record with id AbbrevID from Cursor, resetting the
|
||||
/// internal state.
|
||||
unsigned readRecord(llvm::BitstreamCursor &Cursor, unsigned AbbrevID);
|
||||
Expected<unsigned> readRecord(llvm::BitstreamCursor &Cursor,
|
||||
unsigned AbbrevID);
|
||||
|
||||
/// Is this a module file for a module (rather than a PCH or similar).
|
||||
bool isModule() const { return F->isModule(); }
|
||||
|
@ -2679,7 +2681,10 @@ struct SavedStreamPosition {
|
|||
: Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) {}
|
||||
|
||||
~SavedStreamPosition() {
|
||||
Cursor.JumpToBit(Offset);
|
||||
if (llvm::Error Err = Cursor.JumpToBit(Offset))
|
||||
llvm::report_fatal_error(
|
||||
"Cursor should always be able to go back, failed: " +
|
||||
toString(std::move(Err)));
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
|
@ -122,27 +123,14 @@ class GlobalModuleIndex {
|
|||
public:
|
||||
~GlobalModuleIndex();
|
||||
|
||||
/// An error code returned when trying to read an index.
|
||||
enum ErrorCode {
|
||||
/// No error occurred.
|
||||
EC_None,
|
||||
/// No index was found.
|
||||
EC_NotFound,
|
||||
/// Some other process is currently building the index; it is not
|
||||
/// available yet.
|
||||
EC_Building,
|
||||
/// There was an unspecified I/O error reading or writing the index.
|
||||
EC_IOError
|
||||
};
|
||||
|
||||
/// Read a global index file for the given directory.
|
||||
///
|
||||
/// \param Path The path to the specific module cache where the module files
|
||||
/// for the intended configuration reside.
|
||||
///
|
||||
/// \returns A pair containing the global module index (if it exists) and
|
||||
/// the error code.
|
||||
static std::pair<GlobalModuleIndex *, ErrorCode>
|
||||
/// the error.
|
||||
static std::pair<GlobalModuleIndex *, llvm::Error>
|
||||
readIndex(llvm::StringRef Path);
|
||||
|
||||
/// Returns an iterator for identifiers stored in the index table.
|
||||
|
@ -194,9 +182,9 @@ public:
|
|||
/// creating modules.
|
||||
/// \param Path The path to the directory containing module files, into
|
||||
/// which the global index will be written.
|
||||
static ErrorCode writeIndex(FileManager &FileMgr,
|
||||
const PCHContainerReader &PCHContainerRdr,
|
||||
llvm::StringRef Path);
|
||||
static llvm::Error writeIndex(FileManager &FileMgr,
|
||||
const PCHContainerReader &PCHContainerRdr,
|
||||
llvm::StringRef Path);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1206,8 +1206,10 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
|
|||
else
|
||||
PreambleSrcLocCache.clear();
|
||||
|
||||
if (!Act->Execute())
|
||||
if (llvm::Error Err = Act->Execute()) {
|
||||
consumeError(std::move(Err)); // FIXME this drops errors on the floor.
|
||||
goto error;
|
||||
}
|
||||
|
||||
transferASTDataFromCompilerInstance(*Clang);
|
||||
|
||||
|
@ -1632,7 +1634,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
|
|||
Clang->setASTConsumer(
|
||||
llvm::make_unique<MultiplexConsumer>(std::move(Consumers)));
|
||||
}
|
||||
if (!Act->Execute()) {
|
||||
if (llvm::Error Err = Act->Execute()) {
|
||||
consumeError(std::move(Err)); // FIXME this drops errors on the floor.
|
||||
AST->transferASTDataFromCompilerInstance(*Clang);
|
||||
if (OwnAST && ErrAST)
|
||||
ErrAST->swap(OwnAST);
|
||||
|
@ -2280,7 +2283,9 @@ void ASTUnit::CodeComplete(
|
|||
std::unique_ptr<SyntaxOnlyAction> Act;
|
||||
Act.reset(new SyntaxOnlyAction);
|
||||
if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
|
||||
Act->Execute();
|
||||
if (llvm::Error Err = Act->Execute()) {
|
||||
consumeError(std::move(Err)); // FIXME this drops errors on the floor.
|
||||
}
|
||||
Act->EndSourceFile();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -941,7 +941,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
|
|||
getSourceManager().clearIDTables();
|
||||
|
||||
if (Act.BeginSourceFile(*this, FIF)) {
|
||||
Act.Execute();
|
||||
if (llvm::Error Err = Act.Execute()) {
|
||||
consumeError(std::move(Err)); // FIXME this drops errors on the floor.
|
||||
}
|
||||
Act.EndSourceFile();
|
||||
}
|
||||
}
|
||||
|
@ -2043,9 +2045,16 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(
|
|||
hasPreprocessor()) {
|
||||
llvm::sys::fs::create_directories(
|
||||
getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
|
||||
GlobalModuleIndex::writeIndex(
|
||||
getFileManager(), getPCHContainerReader(),
|
||||
getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
|
||||
if (llvm::Error Err = GlobalModuleIndex::writeIndex(
|
||||
getFileManager(), getPCHContainerReader(),
|
||||
getPreprocessor().getHeaderSearchInfo().getModuleCachePath())) {
|
||||
// FIXME this drops the error on the floor. This code is only used for
|
||||
// typo correction and drops more than just this one source of errors
|
||||
// (such as the directory creation failure above). It should handle the
|
||||
// error.
|
||||
consumeError(std::move(Err));
|
||||
return nullptr;
|
||||
}
|
||||
ModuleManager->resetForReload();
|
||||
ModuleManager->loadGlobalIndex();
|
||||
GlobalIndex = ModuleManager->getGlobalIndex();
|
||||
|
@ -2070,9 +2079,13 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(
|
|||
}
|
||||
}
|
||||
if (RecreateIndex) {
|
||||
GlobalModuleIndex::writeIndex(
|
||||
getFileManager(), getPCHContainerReader(),
|
||||
getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
|
||||
if (llvm::Error Err = GlobalModuleIndex::writeIndex(
|
||||
getFileManager(), getPCHContainerReader(),
|
||||
getPreprocessor().getHeaderSearchInfo().getModuleCachePath())) {
|
||||
// FIXME As above, this drops the error on the floor.
|
||||
consumeError(std::move(Err));
|
||||
return nullptr;
|
||||
}
|
||||
ModuleManager->resetForReload();
|
||||
ModuleManager->loadGlobalIndex();
|
||||
GlobalIndex = ModuleManager->getGlobalIndex();
|
||||
|
|
|
@ -924,7 +924,7 @@ failure:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool FrontendAction::Execute() {
|
||||
llvm::Error FrontendAction::Execute() {
|
||||
CompilerInstance &CI = getCompilerInstance();
|
||||
|
||||
if (CI.hasFrontendTimer()) {
|
||||
|
@ -939,12 +939,18 @@ bool FrontendAction::Execute() {
|
|||
CI.hasPreprocessor()) {
|
||||
StringRef Cache =
|
||||
CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath();
|
||||
if (!Cache.empty())
|
||||
GlobalModuleIndex::writeIndex(CI.getFileManager(),
|
||||
CI.getPCHContainerReader(), Cache);
|
||||
if (!Cache.empty()) {
|
||||
if (llvm::Error Err = GlobalModuleIndex::writeIndex(
|
||||
CI.getFileManager(), CI.getPCHContainerReader(), Cache)) {
|
||||
// FIXME this drops the error on the floor, but
|
||||
// Index/pch-from-libclang.c seems to rely on dropping at least some of
|
||||
// the error conditions!
|
||||
consumeError(std::move(Err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
void FrontendAction::EndSourceFile() {
|
||||
|
|
|
@ -352,7 +352,8 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
|
|||
if (auto CommentHandler = Callbacks.getCommentHandler())
|
||||
Clang->getPreprocessor().addCommentHandler(CommentHandler);
|
||||
|
||||
Act->Execute();
|
||||
if (llvm::Error Err = Act->Execute())
|
||||
return errorToErrorCode(std::move(Err));
|
||||
|
||||
// Run the callbacks.
|
||||
Callbacks.AfterExecute(*Clang);
|
||||
|
|
|
@ -129,7 +129,11 @@ bool FixItRecompile::BeginInvocation(CompilerInstance &CI) {
|
|||
FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings;
|
||||
FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(),
|
||||
CI.getLangOpts(), FixItOpts.get());
|
||||
FixAction->Execute();
|
||||
if (llvm::Error Err = FixAction->Execute()) {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(std::move(Err));
|
||||
return false;
|
||||
}
|
||||
|
||||
err = Rewriter.WriteFixedFiles(&RewrittenFiles);
|
||||
|
||||
|
|
|
@ -41,21 +41,47 @@ std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
|
|||
return SDError::InvalidSignature;
|
||||
|
||||
// Sniff for the signature.
|
||||
if (Stream.Read(8) != 'D' ||
|
||||
Stream.Read(8) != 'I' ||
|
||||
Stream.Read(8) != 'A' ||
|
||||
Stream.Read(8) != 'G')
|
||||
for (unsigned char C : {'D', 'I', 'A', 'G'}) {
|
||||
if (Expected<llvm::SimpleBitstreamCursor::word_t> Res = Stream.Read(8)) {
|
||||
if (Res.get() == C)
|
||||
continue;
|
||||
} else {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(Res.takeError());
|
||||
}
|
||||
return SDError::InvalidSignature;
|
||||
}
|
||||
|
||||
// Read the top level blocks.
|
||||
while (!Stream.AtEndOfStream()) {
|
||||
if (Stream.ReadCode() != llvm::bitc::ENTER_SUBBLOCK)
|
||||
if (Expected<unsigned> Res = Stream.ReadCode()) {
|
||||
if (Res.get() != llvm::bitc::ENTER_SUBBLOCK)
|
||||
return SDError::InvalidDiagnostics;
|
||||
} else {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(Res.takeError());
|
||||
return SDError::InvalidDiagnostics;
|
||||
}
|
||||
|
||||
std::error_code EC;
|
||||
switch (Stream.ReadSubBlockID()) {
|
||||
case llvm::bitc::BLOCKINFO_BLOCK_ID:
|
||||
BlockInfo = Stream.ReadBlockInfoBlock();
|
||||
Expected<unsigned> MaybeSubBlockID = Stream.ReadSubBlockID();
|
||||
if (!MaybeSubBlockID) {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(MaybeSubBlockID.takeError());
|
||||
return SDError::InvalidDiagnostics;
|
||||
}
|
||||
|
||||
switch (MaybeSubBlockID.get()) {
|
||||
case llvm::bitc::BLOCKINFO_BLOCK_ID: {
|
||||
Expected<Optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
|
||||
Stream.ReadBlockInfoBlock();
|
||||
if (!MaybeBlockInfo) {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(MaybeBlockInfo.takeError());
|
||||
return SDError::InvalidDiagnostics;
|
||||
}
|
||||
BlockInfo = std::move(MaybeBlockInfo.get());
|
||||
}
|
||||
if (!BlockInfo)
|
||||
return SDError::MalformedBlockInfoBlock;
|
||||
Stream.setBlockInfo(&*BlockInfo);
|
||||
|
@ -69,8 +95,11 @@ std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
|
|||
return EC;
|
||||
continue;
|
||||
default:
|
||||
if (!Stream.SkipBlock())
|
||||
if (llvm::Error Err = Stream.SkipBlock()) {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(std::move(Err));
|
||||
return SDError::MalformedTopLevelBlock;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -89,11 +118,18 @@ SerializedDiagnosticReader::skipUntilRecordOrBlock(
|
|||
BlockOrRecordID = 0;
|
||||
|
||||
while (!Stream.AtEndOfStream()) {
|
||||
unsigned Code = Stream.ReadCode();
|
||||
unsigned Code;
|
||||
if (Expected<unsigned> Res = Stream.ReadCode())
|
||||
Code = Res.get();
|
||||
else
|
||||
return llvm::errorToErrorCode(Res.takeError());
|
||||
|
||||
switch ((llvm::bitc::FixedAbbrevIDs)Code) {
|
||||
case llvm::bitc::ENTER_SUBBLOCK:
|
||||
BlockOrRecordID = Stream.ReadSubBlockID();
|
||||
if (Expected<unsigned> Res = Stream.ReadSubBlockID())
|
||||
BlockOrRecordID = Res.get();
|
||||
else
|
||||
return llvm::errorToErrorCode(Res.takeError());
|
||||
return Cursor::BlockBegin;
|
||||
|
||||
case llvm::bitc::END_BLOCK:
|
||||
|
@ -102,7 +138,8 @@ SerializedDiagnosticReader::skipUntilRecordOrBlock(
|
|||
return Cursor::BlockEnd;
|
||||
|
||||
case llvm::bitc::DEFINE_ABBREV:
|
||||
Stream.ReadAbbrevRecord();
|
||||
if (llvm::Error Err = Stream.ReadAbbrevRecord())
|
||||
return llvm::errorToErrorCode(std::move(Err));
|
||||
continue;
|
||||
|
||||
case llvm::bitc::UNABBREV_RECORD:
|
||||
|
@ -120,8 +157,12 @@ SerializedDiagnosticReader::skipUntilRecordOrBlock(
|
|||
|
||||
std::error_code
|
||||
SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
|
||||
if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META))
|
||||
if (llvm::Error Err =
|
||||
Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(std::move(Err));
|
||||
return SDError::MalformedMetadataBlock;
|
||||
}
|
||||
|
||||
bool VersionChecked = false;
|
||||
|
||||
|
@ -135,8 +176,11 @@ SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
|
|||
case Cursor::Record:
|
||||
break;
|
||||
case Cursor::BlockBegin:
|
||||
if (Stream.SkipBlock())
|
||||
if (llvm::Error Err = Stream.SkipBlock()) {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(std::move(Err));
|
||||
return SDError::MalformedMetadataBlock;
|
||||
}
|
||||
LLVM_FALLTHROUGH;
|
||||
case Cursor::BlockEnd:
|
||||
if (!VersionChecked)
|
||||
|
@ -145,7 +189,10 @@ SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
|
|||
}
|
||||
|
||||
SmallVector<uint64_t, 1> Record;
|
||||
unsigned RecordID = Stream.readRecord(BlockOrCode, Record);
|
||||
Expected<unsigned> MaybeRecordID = Stream.readRecord(BlockOrCode, Record);
|
||||
if (!MaybeRecordID)
|
||||
return errorToErrorCode(MaybeRecordID.takeError());
|
||||
unsigned RecordID = MaybeRecordID.get();
|
||||
|
||||
if (RecordID == RECORD_VERSION) {
|
||||
if (Record.size() < 1)
|
||||
|
@ -159,8 +206,12 @@ SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
|
|||
|
||||
std::error_code
|
||||
SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
|
||||
if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG))
|
||||
if (llvm::Error Err =
|
||||
Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(std::move(Err));
|
||||
return SDError::MalformedDiagnosticBlock;
|
||||
}
|
||||
|
||||
std::error_code EC;
|
||||
if ((EC = visitStartOfDiagnostic()))
|
||||
|
@ -179,8 +230,11 @@ SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
|
|||
if (BlockOrCode == serialized_diags::BLOCK_DIAG) {
|
||||
if ((EC = readDiagnosticBlock(Stream)))
|
||||
return EC;
|
||||
} else if (!Stream.SkipBlock())
|
||||
} else if (llvm::Error Err = Stream.SkipBlock()) {
|
||||
// FIXME this drops the error on the floor.
|
||||
consumeError(std::move(Err));
|
||||
return SDError::MalformedSubBlock;
|
||||
}
|
||||
continue;
|
||||
case Cursor::BlockEnd:
|
||||
if ((EC = visitEndOfDiagnostic()))
|
||||
|
@ -193,7 +247,11 @@ SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
|
|||
// Read the record.
|
||||
Record.clear();
|
||||
StringRef Blob;
|
||||
unsigned RecID = Stream.readRecord(BlockOrCode, Record, &Blob);
|
||||
Expected<unsigned> MaybeRecID =
|
||||
Stream.readRecord(BlockOrCode, Record, &Blob);
|
||||
if (!MaybeRecID)
|
||||
return errorToErrorCode(MaybeRecID.takeError());
|
||||
unsigned RecID = MaybeRecID.get();
|
||||
|
||||
if (RecID < serialized_diags::RECORD_FIRST ||
|
||||
RecID > serialized_diags::RECORD_LAST)
|
||||
|
|
|
@ -48,7 +48,12 @@ TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
|
|||
// Read the extension block.
|
||||
SmallVector<uint64_t, 4> Record;
|
||||
while (true) {
|
||||
llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
|
||||
llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
|
||||
Stream.advanceSkippingSubblocks();
|
||||
if (!MaybeEntry)
|
||||
(void)MaybeEntry.takeError();
|
||||
llvm::BitstreamEntry Entry = MaybeEntry.get();
|
||||
|
||||
switch (Entry.Kind) {
|
||||
case llvm::BitstreamEntry::SubBlock:
|
||||
case llvm::BitstreamEntry::EndBlock:
|
||||
|
@ -61,8 +66,12 @@ TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
|
|||
|
||||
Record.clear();
|
||||
StringRef Blob;
|
||||
unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
|
||||
switch (RecCode) {
|
||||
Expected<unsigned> MaybeRecCode =
|
||||
Stream.readRecord(Entry.ID, Record, &Blob);
|
||||
if (!MaybeRecCode)
|
||||
fprintf(stderr, "Failed reading rec code: %s\n",
|
||||
toString(MaybeRecCode.takeError()).c_str());
|
||||
switch (MaybeRecCode.get()) {
|
||||
case FIRST_EXTENSION_RECORD_ID: {
|
||||
StringRef Message = Blob.substr(0, Record[0]);
|
||||
fprintf(stderr, "Read extension block message: %s\n",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3679,14 +3679,28 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
|
|||
// Note that we are loading a declaration record.
|
||||
Deserializing ADecl(this);
|
||||
|
||||
DeclsCursor.JumpToBit(Loc.Offset);
|
||||
auto Fail = [](const char *what, llvm::Error &&Err) {
|
||||
llvm::report_fatal_error(Twine("ASTReader::ReadDeclRecord failed ") + what +
|
||||
": " + toString(std::move(Err)));
|
||||
};
|
||||
|
||||
if (llvm::Error JumpFailed = DeclsCursor.JumpToBit(Loc.Offset))
|
||||
Fail("jumping", std::move(JumpFailed));
|
||||
ASTRecordReader Record(*this, *Loc.F);
|
||||
ASTDeclReader Reader(*this, Record, Loc, ID, DeclLoc);
|
||||
unsigned Code = DeclsCursor.ReadCode();
|
||||
Expected<unsigned> MaybeCode = DeclsCursor.ReadCode();
|
||||
if (!MaybeCode)
|
||||
Fail("reading code", MaybeCode.takeError());
|
||||
unsigned Code = MaybeCode.get();
|
||||
|
||||
ASTContext &Context = getContext();
|
||||
Decl *D = nullptr;
|
||||
switch ((DeclCode)Record.readRecord(DeclsCursor, Code)) {
|
||||
Expected<unsigned> MaybeDeclCode = Record.readRecord(DeclsCursor, Code);
|
||||
if (!MaybeDeclCode)
|
||||
llvm::report_fatal_error(
|
||||
"ASTReader::ReadDeclRecord failed reading decl code: " +
|
||||
toString(MaybeDeclCode.takeError()));
|
||||
switch ((DeclCode)MaybeDeclCode.get()) {
|
||||
case DECL_CONTEXT_LEXICAL:
|
||||
case DECL_CONTEXT_VISIBLE:
|
||||
llvm_unreachable("Record cannot be de-serialized with ReadDeclRecord");
|
||||
|
@ -4025,12 +4039,25 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
|
|||
uint64_t Offset = FileAndOffset.second;
|
||||
llvm::BitstreamCursor &Cursor = F->DeclsCursor;
|
||||
SavedStreamPosition SavedPosition(Cursor);
|
||||
Cursor.JumpToBit(Offset);
|
||||
unsigned Code = Cursor.ReadCode();
|
||||
if (llvm::Error JumpFailed = Cursor.JumpToBit(Offset))
|
||||
// FIXME don't do a fatal error.
|
||||
llvm::report_fatal_error(
|
||||
"ASTReader::loadDeclUpdateRecords failed jumping: " +
|
||||
toString(std::move(JumpFailed)));
|
||||
Expected<unsigned> MaybeCode = Cursor.ReadCode();
|
||||
if (!MaybeCode)
|
||||
llvm::report_fatal_error(
|
||||
"ASTReader::loadDeclUpdateRecords failed reading code: " +
|
||||
toString(MaybeCode.takeError()));
|
||||
unsigned Code = MaybeCode.get();
|
||||
ASTRecordReader Record(*this, *F);
|
||||
unsigned RecCode = Record.readRecord(Cursor, Code);
|
||||
(void)RecCode;
|
||||
assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!");
|
||||
if (Expected<unsigned> MaybeRecCode = Record.readRecord(Cursor, Code))
|
||||
assert(MaybeRecCode.get() == DECL_UPDATES &&
|
||||
"Expected DECL_UPDATES record!");
|
||||
else
|
||||
llvm::report_fatal_error(
|
||||
"ASTReader::loadDeclUpdateRecords failed reading rec code: " +
|
||||
toString(MaybeCode.takeError()));
|
||||
|
||||
ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID,
|
||||
SourceLocation());
|
||||
|
@ -4094,13 +4121,25 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) {
|
|||
|
||||
llvm::BitstreamCursor &Cursor = M->DeclsCursor;
|
||||
SavedStreamPosition SavedPosition(Cursor);
|
||||
Cursor.JumpToBit(LocalOffset);
|
||||
if (llvm::Error JumpFailed = Cursor.JumpToBit(LocalOffset))
|
||||
llvm::report_fatal_error(
|
||||
"ASTReader::loadPendingDeclChain failed jumping: " +
|
||||
toString(std::move(JumpFailed)));
|
||||
|
||||
RecordData Record;
|
||||
unsigned Code = Cursor.ReadCode();
|
||||
unsigned RecCode = Cursor.readRecord(Code, Record);
|
||||
(void)RecCode;
|
||||
assert(RecCode == LOCAL_REDECLARATIONS && "expected LOCAL_REDECLARATIONS record!");
|
||||
Expected<unsigned> MaybeCode = Cursor.ReadCode();
|
||||
if (!MaybeCode)
|
||||
llvm::report_fatal_error(
|
||||
"ASTReader::loadPendingDeclChain failed reading code: " +
|
||||
toString(MaybeCode.takeError()));
|
||||
unsigned Code = MaybeCode.get();
|
||||
if (Expected<unsigned> MaybeRecCode = Cursor.readRecord(Code, Record))
|
||||
assert(MaybeRecCode.get() == LOCAL_REDECLARATIONS &&
|
||||
"expected LOCAL_REDECLARATIONS record!");
|
||||
else
|
||||
llvm::report_fatal_error(
|
||||
"ASTReader::loadPendingDeclChain failed reading rec code: " +
|
||||
toString(MaybeCode.takeError()));
|
||||
|
||||
// FIXME: We have several different dispatches on decl kind here; maybe
|
||||
// we should instead generate one loop per kind and dispatch up-front?
|
||||
|
|
|
@ -2392,7 +2392,13 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
|||
Stmt::EmptyShell Empty;
|
||||
|
||||
while (true) {
|
||||
llvm::BitstreamEntry Entry = Cursor.advanceSkippingSubblocks();
|
||||
llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
|
||||
Cursor.advanceSkippingSubblocks();
|
||||
if (!MaybeEntry) {
|
||||
Error(toString(MaybeEntry.takeError()));
|
||||
return nullptr;
|
||||
}
|
||||
llvm::BitstreamEntry Entry = MaybeEntry.get();
|
||||
|
||||
switch (Entry.Kind) {
|
||||
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
|
||||
|
@ -2410,7 +2416,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
|||
Stmt *S = nullptr;
|
||||
bool Finished = false;
|
||||
bool IsStmtReference = false;
|
||||
switch ((StmtCode)Record.readRecord(Cursor, Entry.ID)) {
|
||||
Expected<unsigned> MaybeStmtCode = Record.readRecord(Cursor, Entry.ID);
|
||||
if (!MaybeStmtCode) {
|
||||
Error(toString(MaybeStmtCode.takeError()));
|
||||
return nullptr;
|
||||
}
|
||||
switch ((StmtCode)MaybeStmtCode.get()) {
|
||||
case STMT_STOP:
|
||||
Finished = true;
|
||||
break;
|
||||
|
|
|
@ -128,12 +128,21 @@ GlobalModuleIndex::GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer,
|
|||
llvm::BitstreamCursor Cursor)
|
||||
: Buffer(std::move(Buffer)), IdentifierIndex(), NumIdentifierLookups(),
|
||||
NumIdentifierLookupHits() {
|
||||
auto Fail = [&Buffer](llvm::Error &&Err) {
|
||||
report_fatal_error("Module index '" + Buffer->getBufferIdentifier() +
|
||||
"' failed: " + toString(std::move(Err)));
|
||||
};
|
||||
|
||||
llvm::TimeTraceScope TimeScope("Module LoadIndex", StringRef(""));
|
||||
// Read the global index.
|
||||
bool InGlobalIndexBlock = false;
|
||||
bool Done = false;
|
||||
while (!Done) {
|
||||
llvm::BitstreamEntry Entry = Cursor.advance();
|
||||
llvm::BitstreamEntry Entry;
|
||||
if (Expected<llvm::BitstreamEntry> Res = Cursor.advance())
|
||||
Entry = Res.get();
|
||||
else
|
||||
Fail(Res.takeError());
|
||||
|
||||
switch (Entry.Kind) {
|
||||
case llvm::BitstreamEntry::Error:
|
||||
|
@ -157,19 +166,23 @@ GlobalModuleIndex::GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer,
|
|||
|
||||
case llvm::BitstreamEntry::SubBlock:
|
||||
if (!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) {
|
||||
if (Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID))
|
||||
return;
|
||||
|
||||
if (llvm::Error Err = Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID))
|
||||
Fail(std::move(Err));
|
||||
InGlobalIndexBlock = true;
|
||||
} else if (Cursor.SkipBlock()) {
|
||||
return;
|
||||
}
|
||||
} else if (llvm::Error Err = Cursor.SkipBlock())
|
||||
Fail(std::move(Err));
|
||||
continue;
|
||||
}
|
||||
|
||||
SmallVector<uint64_t, 64> Record;
|
||||
StringRef Blob;
|
||||
switch ((IndexRecordTypes)Cursor.readRecord(Entry.ID, Record, &Blob)) {
|
||||
Expected<unsigned> MaybeIndexRecord =
|
||||
Cursor.readRecord(Entry.ID, Record, &Blob);
|
||||
if (!MaybeIndexRecord)
|
||||
Fail(MaybeIndexRecord.takeError());
|
||||
IndexRecordTypes IndexRecord =
|
||||
static_cast<IndexRecordTypes>(MaybeIndexRecord.get());
|
||||
switch (IndexRecord) {
|
||||
case INDEX_METADATA:
|
||||
// Make sure that the version matches.
|
||||
if (Record.size() < 1 || Record[0] != CurrentVersion)
|
||||
|
@ -234,7 +247,7 @@ GlobalModuleIndex::~GlobalModuleIndex() {
|
|||
delete static_cast<IdentifierIndexTable *>(IdentifierIndex);
|
||||
}
|
||||
|
||||
std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode>
|
||||
std::pair<GlobalModuleIndex *, llvm::Error>
|
||||
GlobalModuleIndex::readIndex(StringRef Path) {
|
||||
// Load the index file, if it's there.
|
||||
llvm::SmallString<128> IndexPath;
|
||||
|
@ -244,22 +257,26 @@ GlobalModuleIndex::readIndex(StringRef Path) {
|
|||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> BufferOrErr =
|
||||
llvm::MemoryBuffer::getFile(IndexPath.c_str());
|
||||
if (!BufferOrErr)
|
||||
return std::make_pair(nullptr, EC_NotFound);
|
||||
return std::make_pair(nullptr,
|
||||
llvm::errorCodeToError(BufferOrErr.getError()));
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get());
|
||||
|
||||
/// The main bitstream cursor for the main block.
|
||||
llvm::BitstreamCursor Cursor(*Buffer);
|
||||
|
||||
// Sniff for the signature.
|
||||
if (Cursor.Read(8) != 'B' ||
|
||||
Cursor.Read(8) != 'C' ||
|
||||
Cursor.Read(8) != 'G' ||
|
||||
Cursor.Read(8) != 'I') {
|
||||
return std::make_pair(nullptr, EC_IOError);
|
||||
for (unsigned char C : {'B', 'C', 'G', 'I'}) {
|
||||
if (Expected<llvm::SimpleBitstreamCursor::word_t> Res = Cursor.Read(8)) {
|
||||
if (Res.get() != C)
|
||||
return std::make_pair(
|
||||
nullptr, llvm::createStringError(std::errc::illegal_byte_sequence,
|
||||
"expected signature BCGI"));
|
||||
} else
|
||||
return std::make_pair(nullptr, Res.takeError());
|
||||
}
|
||||
|
||||
return std::make_pair(new GlobalModuleIndex(std::move(Buffer), Cursor),
|
||||
EC_None);
|
||||
llvm::Error::success());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -438,9 +455,7 @@ namespace {
|
|||
: FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {}
|
||||
|
||||
/// Load the contents of the given module file into the builder.
|
||||
///
|
||||
/// \returns true if an error occurred, false otherwise.
|
||||
bool loadModuleFile(const FileEntry *File);
|
||||
llvm::Error loadModuleFile(const FileEntry *File);
|
||||
|
||||
/// Write the index to the given bitstream.
|
||||
/// \returns true if an error occurred, false otherwise.
|
||||
|
@ -511,24 +526,25 @@ namespace {
|
|||
};
|
||||
}
|
||||
|
||||
bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
|
||||
llvm::Error GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
|
||||
// Open the module file.
|
||||
|
||||
auto Buffer = FileMgr.getBufferForFile(File, /*isVolatile=*/true);
|
||||
if (!Buffer) {
|
||||
return true;
|
||||
}
|
||||
if (!Buffer)
|
||||
return llvm::createStringError(Buffer.getError(),
|
||||
"failed getting buffer for module file");
|
||||
|
||||
// Initialize the input stream
|
||||
llvm::BitstreamCursor InStream(PCHContainerRdr.ExtractPCH(**Buffer));
|
||||
|
||||
// Sniff for the signature.
|
||||
if (InStream.Read(8) != 'C' ||
|
||||
InStream.Read(8) != 'P' ||
|
||||
InStream.Read(8) != 'C' ||
|
||||
InStream.Read(8) != 'H') {
|
||||
return true;
|
||||
}
|
||||
for (unsigned char C : {'C', 'P', 'C', 'H'})
|
||||
if (Expected<llvm::SimpleBitstreamCursor::word_t> Res = InStream.Read(8)) {
|
||||
if (Res.get() != C)
|
||||
return llvm::createStringError(std::errc::illegal_byte_sequence,
|
||||
"expected signature CPCH");
|
||||
} else
|
||||
return Res.takeError();
|
||||
|
||||
// Record this module file and assign it a unique ID (if it doesn't have
|
||||
// one already).
|
||||
|
@ -538,7 +554,11 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
|
|||
enum { Other, ControlBlock, ASTBlock, DiagnosticOptionsBlock } State = Other;
|
||||
bool Done = false;
|
||||
while (!Done) {
|
||||
llvm::BitstreamEntry Entry = InStream.advance();
|
||||
Expected<llvm::BitstreamEntry> MaybeEntry = InStream.advance();
|
||||
if (!MaybeEntry)
|
||||
return MaybeEntry.takeError();
|
||||
llvm::BitstreamEntry Entry = MaybeEntry.get();
|
||||
|
||||
switch (Entry.Kind) {
|
||||
case llvm::BitstreamEntry::Error:
|
||||
Done = true;
|
||||
|
@ -547,8 +567,10 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
|
|||
case llvm::BitstreamEntry::Record:
|
||||
// In the 'other' state, just skip the record. We don't care.
|
||||
if (State == Other) {
|
||||
InStream.skipRecord(Entry.ID);
|
||||
continue;
|
||||
if (llvm::Expected<unsigned> Skipped = InStream.skipRecord(Entry.ID))
|
||||
continue;
|
||||
else
|
||||
return Skipped.takeError();
|
||||
}
|
||||
|
||||
// Handle potentially-interesting records below.
|
||||
|
@ -556,8 +578,8 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
|
|||
|
||||
case llvm::BitstreamEntry::SubBlock:
|
||||
if (Entry.ID == CONTROL_BLOCK_ID) {
|
||||
if (InStream.EnterSubBlock(CONTROL_BLOCK_ID))
|
||||
return true;
|
||||
if (llvm::Error Err = InStream.EnterSubBlock(CONTROL_BLOCK_ID))
|
||||
return Err;
|
||||
|
||||
// Found the control block.
|
||||
State = ControlBlock;
|
||||
|
@ -565,8 +587,8 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
|
|||
}
|
||||
|
||||
if (Entry.ID == AST_BLOCK_ID) {
|
||||
if (InStream.EnterSubBlock(AST_BLOCK_ID))
|
||||
return true;
|
||||
if (llvm::Error Err = InStream.EnterSubBlock(AST_BLOCK_ID))
|
||||
return Err;
|
||||
|
||||
// Found the AST block.
|
||||
State = ASTBlock;
|
||||
|
@ -574,16 +596,16 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
|
|||
}
|
||||
|
||||
if (Entry.ID == UNHASHED_CONTROL_BLOCK_ID) {
|
||||
if (InStream.EnterSubBlock(UNHASHED_CONTROL_BLOCK_ID))
|
||||
return true;
|
||||
if (llvm::Error Err = InStream.EnterSubBlock(UNHASHED_CONTROL_BLOCK_ID))
|
||||
return Err;
|
||||
|
||||
// Found the Diagnostic Options block.
|
||||
State = DiagnosticOptionsBlock;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (InStream.SkipBlock())
|
||||
return true;
|
||||
if (llvm::Error Err = InStream.SkipBlock())
|
||||
return Err;
|
||||
|
||||
continue;
|
||||
|
||||
|
@ -595,7 +617,10 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
|
|||
// Read the given record.
|
||||
SmallVector<uint64_t, 64> Record;
|
||||
StringRef Blob;
|
||||
unsigned Code = InStream.readRecord(Entry.ID, Record, &Blob);
|
||||
Expected<unsigned> MaybeCode = InStream.readRecord(Entry.ID, Record, &Blob);
|
||||
if (!MaybeCode)
|
||||
return MaybeCode.takeError();
|
||||
unsigned Code = MaybeCode.get();
|
||||
|
||||
// Handle module dependencies.
|
||||
if (State == ControlBlock && Code == IMPORTS) {
|
||||
|
@ -637,7 +662,9 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
|
|||
/*cacheFailure=*/false);
|
||||
|
||||
if (!DependsOnFile)
|
||||
return true;
|
||||
return llvm::createStringError(std::errc::bad_file_descriptor,
|
||||
"imported file \"%s\" not found",
|
||||
ImportedFile.c_str());
|
||||
|
||||
// Save the information in ImportedModuleFileInfo so we can verify after
|
||||
// loading all pcms.
|
||||
|
@ -682,7 +709,7 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
|
|||
// We don't care about this record.
|
||||
}
|
||||
|
||||
return false;
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -820,7 +847,7 @@ bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
|
|||
return false;
|
||||
}
|
||||
|
||||
GlobalModuleIndex::ErrorCode
|
||||
llvm::Error
|
||||
GlobalModuleIndex::writeIndex(FileManager &FileMgr,
|
||||
const PCHContainerReader &PCHContainerRdr,
|
||||
StringRef Path) {
|
||||
|
@ -833,7 +860,7 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
|
|||
llvm::LockFileManager Locked(IndexPath);
|
||||
switch (Locked) {
|
||||
case llvm::LockFileManager::LFS_Error:
|
||||
return EC_IOError;
|
||||
return llvm::createStringError(std::errc::io_error, "LFS error");
|
||||
|
||||
case llvm::LockFileManager::LFS_Owned:
|
||||
// We're responsible for building the index ourselves. Do so below.
|
||||
|
@ -842,7 +869,8 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
|
|||
case llvm::LockFileManager::LFS_Shared:
|
||||
// Someone else is responsible for building the index. We don't care
|
||||
// when they finish, so we're done.
|
||||
return EC_Building;
|
||||
return llvm::createStringError(std::errc::device_or_resource_busy,
|
||||
"someone else is building the index");
|
||||
}
|
||||
|
||||
// The module index builder.
|
||||
|
@ -859,7 +887,8 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
|
|||
// in the process of rebuilding a module. They'll rebuild the index
|
||||
// at the end of that translation unit, so we don't have to.
|
||||
if (llvm::sys::path::extension(D->path()) == ".pcm.lock")
|
||||
return EC_Building;
|
||||
return llvm::createStringError(std::errc::device_or_resource_busy,
|
||||
"someone else is building the index");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -870,8 +899,8 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
|
|||
continue;
|
||||
|
||||
// Load this module file.
|
||||
if (Builder.loadModuleFile(ModuleFile))
|
||||
return EC_IOError;
|
||||
if (llvm::Error Err = Builder.loadModuleFile(ModuleFile))
|
||||
return Err;
|
||||
}
|
||||
|
||||
// The output buffer, into which the global index will be written.
|
||||
|
@ -879,7 +908,8 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
|
|||
{
|
||||
llvm::BitstreamWriter OutputStream(OutputBuffer);
|
||||
if (Builder.writeIndex(OutputStream))
|
||||
return EC_IOError;
|
||||
return llvm::createStringError(std::errc::io_error,
|
||||
"failed writing index");
|
||||
}
|
||||
|
||||
// Write the global index file to a temporary file.
|
||||
|
@ -887,31 +917,32 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
|
|||
int TmpFD;
|
||||
if (llvm::sys::fs::createUniqueFile(IndexPath + "-%%%%%%%%", TmpFD,
|
||||
IndexTmpPath))
|
||||
return EC_IOError;
|
||||
return llvm::createStringError(std::errc::io_error,
|
||||
"failed creating unique file");
|
||||
|
||||
// Open the temporary global index file for output.
|
||||
llvm::raw_fd_ostream Out(TmpFD, true);
|
||||
if (Out.has_error())
|
||||
return EC_IOError;
|
||||
return llvm::createStringError(Out.error(), "failed outputting to stream");
|
||||
|
||||
// Write the index.
|
||||
Out.write(OutputBuffer.data(), OutputBuffer.size());
|
||||
Out.close();
|
||||
if (Out.has_error())
|
||||
return EC_IOError;
|
||||
return llvm::createStringError(Out.error(), "failed writing to stream");
|
||||
|
||||
// Remove the old index file. It isn't relevant any more.
|
||||
llvm::sys::fs::remove(IndexPath);
|
||||
|
||||
// Rename the newly-written index file to the proper name.
|
||||
if (llvm::sys::fs::rename(IndexTmpPath, IndexPath)) {
|
||||
// Rename failed; just remove the
|
||||
if (std::error_code Err = llvm::sys::fs::rename(IndexTmpPath, IndexPath)) {
|
||||
// Remove the file on failure, don't check whether removal succeeded.
|
||||
llvm::sys::fs::remove(IndexTmpPath);
|
||||
return EC_IOError;
|
||||
return llvm::createStringError(Err, "failed renaming file \"%s\" to \"%s\"",
|
||||
IndexTmpPath.c_str(), IndexPath.c_str());
|
||||
}
|
||||
|
||||
// We're done.
|
||||
return EC_None;
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
// - a/../b/ and b/ are not considered the same
|
||||
// - on Windows, c:\ and C:\ (only different in case) are not the same
|
||||
|
||||
// RUN: rm -rf %t.mcp %t.h.pch
|
||||
// RUN: %clang_cc1 -fsyntax-only %s -verify
|
||||
// RUN: c-index-test -write-pch %t.h.pch %s -fmodules -fmodules-cache-path=%t.mcp -Xclang -triple -Xclang x86_64-apple-darwin
|
||||
// RUN: %clang -fsyntax-only -include %t.h %s -Xclang -verify -fmodules -fmodules-cache-path=%t.mcp -Xclang -detailed-preprocessing-record -Xclang -triple -Xclang x86_64-apple-darwin -Xclang -fallow-pch-with-compiler-errors
|
||||
|
|
|
@ -97,7 +97,7 @@ private:
|
|||
unsigned BitsInCurWord = 0;
|
||||
|
||||
public:
|
||||
static const size_t MaxChunkSize = sizeof(word_t) * 8;
|
||||
static const constexpr size_t MaxChunkSize = sizeof(word_t) * 8;
|
||||
|
||||
SimpleBitstreamCursor() = default;
|
||||
explicit SimpleBitstreamCursor(ArrayRef<uint8_t> BitcodeBytes)
|
||||
|
@ -127,7 +127,7 @@ public:
|
|||
ArrayRef<uint8_t> getBitcodeBytes() const { return BitcodeBytes; }
|
||||
|
||||
/// Reset the stream to the specified bit number.
|
||||
void JumpToBit(uint64_t BitNo) {
|
||||
Error JumpToBit(uint64_t BitNo) {
|
||||
size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1);
|
||||
unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1));
|
||||
assert(canSkipToPos(ByteNo) && "Invalid location");
|
||||
|
@ -137,8 +137,14 @@ public:
|
|||
BitsInCurWord = 0;
|
||||
|
||||
// Skip over any bits that are already consumed.
|
||||
if (WordBitNo)
|
||||
Read(WordBitNo);
|
||||
if (WordBitNo) {
|
||||
if (Expected<word_t> Res = Read(WordBitNo))
|
||||
return Error::success();
|
||||
else
|
||||
return Res.takeError();
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// Get a pointer into the bitstream at the specified byte offset.
|
||||
|
@ -154,9 +160,11 @@ public:
|
|||
return getPointerToByte(BitNo / 8, NumBytes);
|
||||
}
|
||||
|
||||
void fillCurWord() {
|
||||
Error fillCurWord() {
|
||||
if (NextChar >= BitcodeBytes.size())
|
||||
report_fatal_error("Unexpected end of file");
|
||||
return createStringError(std::errc::io_error,
|
||||
"Unexpected end of file reading %u of %u bytes",
|
||||
NextChar, BitcodeBytes.size());
|
||||
|
||||
// Read the next word from the stream.
|
||||
const uint8_t *NextCharPtr = BitcodeBytes.data() + NextChar;
|
||||
|
@ -175,9 +183,10 @@ public:
|
|||
}
|
||||
NextChar += BytesRead;
|
||||
BitsInCurWord = BytesRead * 8;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
word_t Read(unsigned NumBits) {
|
||||
Expected<word_t> Read(unsigned NumBits) {
|
||||
static const unsigned BitsInWord = MaxChunkSize;
|
||||
|
||||
assert(NumBits && NumBits <= BitsInWord &&
|
||||
|
@ -199,11 +208,14 @@ public:
|
|||
word_t R = BitsInCurWord ? CurWord : 0;
|
||||
unsigned BitsLeft = NumBits - BitsInCurWord;
|
||||
|
||||
fillCurWord();
|
||||
if (Error fillResult = fillCurWord())
|
||||
return std::move(fillResult);
|
||||
|
||||
// If we run out of data, abort.
|
||||
if (BitsLeft > BitsInCurWord)
|
||||
report_fatal_error("Unexpected end of file");
|
||||
return createStringError(std::errc::io_error,
|
||||
"Unexpected end of file reading %u of %u bits",
|
||||
BitsInCurWord, BitsLeft);
|
||||
|
||||
word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft));
|
||||
|
||||
|
@ -217,8 +229,12 @@ public:
|
|||
return R;
|
||||
}
|
||||
|
||||
uint32_t ReadVBR(unsigned NumBits) {
|
||||
uint32_t Piece = Read(NumBits);
|
||||
Expected<uint32_t> ReadVBR(unsigned NumBits) {
|
||||
Expected<unsigned> MaybeRead = Read(NumBits);
|
||||
if (!MaybeRead)
|
||||
return MaybeRead;
|
||||
uint32_t Piece = MaybeRead.get();
|
||||
|
||||
if ((Piece & (1U << (NumBits-1))) == 0)
|
||||
return Piece;
|
||||
|
||||
|
@ -231,14 +247,21 @@ public:
|
|||
return Result;
|
||||
|
||||
NextBit += NumBits-1;
|
||||
Piece = Read(NumBits);
|
||||
MaybeRead = Read(NumBits);
|
||||
if (!MaybeRead)
|
||||
return MaybeRead;
|
||||
Piece = MaybeRead.get();
|
||||
}
|
||||
}
|
||||
|
||||
// Read a VBR that may have a value up to 64-bits in size. The chunk size of
|
||||
// the VBR must still be <= 32 bits though.
|
||||
uint64_t ReadVBR64(unsigned NumBits) {
|
||||
uint32_t Piece = Read(NumBits);
|
||||
Expected<uint64_t> ReadVBR64(unsigned NumBits) {
|
||||
Expected<unsigned> MaybeRead = Read(NumBits);
|
||||
if (!MaybeRead)
|
||||
return MaybeRead;
|
||||
uint32_t Piece = MaybeRead.get();
|
||||
|
||||
if ((Piece & (1U << (NumBits-1))) == 0)
|
||||
return uint64_t(Piece);
|
||||
|
||||
|
@ -251,7 +274,10 @@ public:
|
|||
return Result;
|
||||
|
||||
NextBit += NumBits-1;
|
||||
Piece = Read(NumBits);
|
||||
MaybeRead = Read(NumBits);
|
||||
if (!MaybeRead)
|
||||
return MaybeRead;
|
||||
Piece = MaybeRead.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,12 +391,16 @@ public:
|
|||
};
|
||||
|
||||
/// Advance the current bitstream, returning the next entry in the stream.
|
||||
BitstreamEntry advance(unsigned Flags = 0) {
|
||||
Expected<BitstreamEntry> advance(unsigned Flags = 0) {
|
||||
while (true) {
|
||||
if (AtEndOfStream())
|
||||
return BitstreamEntry::getError();
|
||||
|
||||
unsigned Code = ReadCode();
|
||||
Expected<unsigned> MaybeCode = ReadCode();
|
||||
if (!MaybeCode)
|
||||
return MaybeCode.takeError();
|
||||
unsigned Code = MaybeCode.get();
|
||||
|
||||
if (Code == bitc::END_BLOCK) {
|
||||
// Pop the end of the block unless Flags tells us not to.
|
||||
if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
|
||||
|
@ -378,14 +408,19 @@ public:
|
|||
return BitstreamEntry::getEndBlock();
|
||||
}
|
||||
|
||||
if (Code == bitc::ENTER_SUBBLOCK)
|
||||
return BitstreamEntry::getSubBlock(ReadSubBlockID());
|
||||
if (Code == bitc::ENTER_SUBBLOCK) {
|
||||
if (Expected<unsigned> MaybeSubBlock = ReadSubBlockID())
|
||||
return BitstreamEntry::getSubBlock(MaybeSubBlock.get());
|
||||
else
|
||||
return MaybeSubBlock.takeError();
|
||||
}
|
||||
|
||||
if (Code == bitc::DEFINE_ABBREV &&
|
||||
!(Flags & AF_DontAutoprocessAbbrevs)) {
|
||||
// We read and accumulate abbrev's, the client can't do anything with
|
||||
// them anyway.
|
||||
ReadAbbrevRecord();
|
||||
if (Error Err = ReadAbbrevRecord())
|
||||
return std::move(Err);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -395,53 +430,66 @@ public:
|
|||
|
||||
/// This is a convenience function for clients that don't expect any
|
||||
/// subblocks. This just skips over them automatically.
|
||||
BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
|
||||
Expected<BitstreamEntry> advanceSkippingSubblocks(unsigned Flags = 0) {
|
||||
while (true) {
|
||||
// If we found a normal entry, return it.
|
||||
BitstreamEntry Entry = advance(Flags);
|
||||
Expected<BitstreamEntry> MaybeEntry = advance(Flags);
|
||||
if (!MaybeEntry)
|
||||
return MaybeEntry;
|
||||
BitstreamEntry Entry = MaybeEntry.get();
|
||||
|
||||
if (Entry.Kind != BitstreamEntry::SubBlock)
|
||||
return Entry;
|
||||
|
||||
// If we found a sub-block, just skip over it and check the next entry.
|
||||
if (SkipBlock())
|
||||
return BitstreamEntry::getError();
|
||||
if (Error Err = SkipBlock())
|
||||
return std::move(Err);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned ReadCode() {
|
||||
return Read(CurCodeSize);
|
||||
}
|
||||
Expected<unsigned> ReadCode() { return Read(CurCodeSize); }
|
||||
|
||||
// Block header:
|
||||
// [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
|
||||
|
||||
/// Having read the ENTER_SUBBLOCK code, read the BlockID for the block.
|
||||
unsigned ReadSubBlockID() {
|
||||
return ReadVBR(bitc::BlockIDWidth);
|
||||
}
|
||||
Expected<unsigned> ReadSubBlockID() { return ReadVBR(bitc::BlockIDWidth); }
|
||||
|
||||
/// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body
|
||||
/// of this block. If the block record is malformed, return true.
|
||||
bool SkipBlock() {
|
||||
// Read and ignore the codelen value. Since we are skipping this block, we
|
||||
// don't care what code widths are used inside of it.
|
||||
ReadVBR(bitc::CodeLenWidth);
|
||||
/// of this block.
|
||||
Error SkipBlock() {
|
||||
// Read and ignore the codelen value.
|
||||
if (Expected<uint32_t> Res = ReadVBR(bitc::CodeLenWidth))
|
||||
; // Since we are skipping this block, we don't care what code widths are
|
||||
// used inside of it.
|
||||
else
|
||||
return Res.takeError();
|
||||
|
||||
SkipToFourByteBoundary();
|
||||
size_t NumFourBytes = Read(bitc::BlockSizeWidth);
|
||||
Expected<unsigned> MaybeNum = Read(bitc::BlockSizeWidth);
|
||||
if (!MaybeNum)
|
||||
return MaybeNum.takeError();
|
||||
size_t NumFourBytes = MaybeNum.get();
|
||||
|
||||
// Check that the block wasn't partially defined, and that the offset isn't
|
||||
// bogus.
|
||||
size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8;
|
||||
if (AtEndOfStream() || !canSkipToPos(SkipTo/8))
|
||||
return true;
|
||||
size_t SkipTo = GetCurrentBitNo() + NumFourBytes * 4 * 8;
|
||||
if (AtEndOfStream())
|
||||
return createStringError(std::errc::illegal_byte_sequence,
|
||||
"can't skip block: already at end of stream");
|
||||
if (!canSkipToPos(SkipTo / 8))
|
||||
return createStringError(std::errc::illegal_byte_sequence,
|
||||
"can't skip to bit %zu from %" PRIu64, SkipTo,
|
||||
GetCurrentBitNo());
|
||||
|
||||
JumpToBit(SkipTo);
|
||||
return false;
|
||||
if (Error Res = JumpToBit(SkipTo))
|
||||
return Res;
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// Having read the ENTER_SUBBLOCK abbrevid, enter the block, and return true
|
||||
/// if the block has an error.
|
||||
bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr);
|
||||
/// Having read the ENTER_SUBBLOCK abbrevid, and enter the block.
|
||||
Error EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr);
|
||||
|
||||
bool ReadBlockEnd() {
|
||||
if (BlockScope.empty()) return true;
|
||||
|
@ -476,22 +524,23 @@ public:
|
|||
}
|
||||
|
||||
/// Read the current record and discard it, returning the code for the record.
|
||||
unsigned skipRecord(unsigned AbbrevID);
|
||||
Expected<unsigned> skipRecord(unsigned AbbrevID);
|
||||
|
||||
unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals,
|
||||
StringRef *Blob = nullptr);
|
||||
Expected<unsigned> readRecord(unsigned AbbrevID,
|
||||
SmallVectorImpl<uint64_t> &Vals,
|
||||
StringRef *Blob = nullptr);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Abbrev Processing
|
||||
//===--------------------------------------------------------------------===//
|
||||
void ReadAbbrevRecord();
|
||||
Error ReadAbbrevRecord();
|
||||
|
||||
/// Read and return a block info block from the bitstream. If an error was
|
||||
/// encountered, return None.
|
||||
///
|
||||
/// \param ReadBlockInfoNames Whether to read block/record name information in
|
||||
/// the BlockInfo block. Only llvm-bcanalyzer uses this.
|
||||
Optional<BitstreamBlockInfo>
|
||||
Expected<Optional<BitstreamBlockInfo>>
|
||||
ReadBlockInfoBlock(bool ReadBlockInfoNames = false);
|
||||
|
||||
/// Set the block info to be used by this BitstreamCursor to interpret
|
||||
|
|
|
@ -1160,8 +1160,8 @@ private:
|
|||
|
||||
/// Create formatted StringError object.
|
||||
template <typename... Ts>
|
||||
Error createStringError(std::error_code EC, char const *Fmt,
|
||||
const Ts &... Vals) {
|
||||
inline Error createStringError(std::error_code EC, char const *Fmt,
|
||||
const Ts &... Vals) {
|
||||
std::string Buffer;
|
||||
raw_string_ostream Stream(Buffer);
|
||||
Stream << format(Fmt, Vals...);
|
||||
|
@ -1170,6 +1170,12 @@ Error createStringError(std::error_code EC, char const *Fmt,
|
|||
|
||||
Error createStringError(std::error_code EC, char const *Msg);
|
||||
|
||||
template <typename... Ts>
|
||||
inline Error createStringError(std::errc EC, char const *Fmt,
|
||||
const Ts &... Vals) {
|
||||
return createStringError(std::make_error_code(EC), Fmt, Vals...);
|
||||
}
|
||||
|
||||
/// This class wraps a filename and another Error.
|
||||
///
|
||||
/// In some cases, an error needs to live along a 'source' name, in order to
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,9 +17,8 @@ using namespace llvm;
|
|||
// BitstreamCursor implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
|
||||
/// the block, and return true if the block has an error.
|
||||
bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {
|
||||
/// Having read the ENTER_SUBBLOCK abbrevid, enter the block.
|
||||
Error BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {
|
||||
// Save the current block's state on BlockScope.
|
||||
BlockScope.push_back(Block(CurCodeSize));
|
||||
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
|
||||
|
@ -34,21 +33,39 @@ bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {
|
|||
}
|
||||
|
||||
// Get the codesize of this block.
|
||||
CurCodeSize = ReadVBR(bitc::CodeLenWidth);
|
||||
// We can't read more than MaxChunkSize at a time
|
||||
Expected<uint32_t> MaybeVBR = ReadVBR(bitc::CodeLenWidth);
|
||||
if (!MaybeVBR)
|
||||
return MaybeVBR.takeError();
|
||||
CurCodeSize = MaybeVBR.get();
|
||||
|
||||
if (CurCodeSize > MaxChunkSize)
|
||||
return true;
|
||||
return llvm::createStringError(
|
||||
std::errc::illegal_byte_sequence,
|
||||
"can't read more than %zu at a time, trying to read %u", +MaxChunkSize,
|
||||
CurCodeSize);
|
||||
|
||||
SkipToFourByteBoundary();
|
||||
unsigned NumWords = Read(bitc::BlockSizeWidth);
|
||||
if (NumWordsP) *NumWordsP = NumWords;
|
||||
Expected<word_t> MaybeNum = Read(bitc::BlockSizeWidth);
|
||||
if (!MaybeNum)
|
||||
return MaybeNum.takeError();
|
||||
word_t NumWords = MaybeNum.get();
|
||||
if (NumWordsP)
|
||||
*NumWordsP = NumWords;
|
||||
|
||||
// Validate that this block is sane.
|
||||
return CurCodeSize == 0 || AtEndOfStream();
|
||||
if (CurCodeSize == 0)
|
||||
return llvm::createStringError(
|
||||
std::errc::illegal_byte_sequence,
|
||||
"can't enter sub-block: current code size is 0");
|
||||
if (AtEndOfStream())
|
||||
return llvm::createStringError(
|
||||
std::errc::illegal_byte_sequence,
|
||||
"can't enter sub block: already at end of stream");
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static uint64_t readAbbreviatedField(BitstreamCursor &Cursor,
|
||||
const BitCodeAbbrevOp &Op) {
|
||||
static Expected<uint64_t> readAbbreviatedField(BitstreamCursor &Cursor,
|
||||
const BitCodeAbbrevOp &Op) {
|
||||
assert(!Op.isLiteral() && "Not to be used with literals!");
|
||||
|
||||
// Decode the value as we are commanded.
|
||||
|
@ -63,13 +80,16 @@ static uint64_t readAbbreviatedField(BitstreamCursor &Cursor,
|
|||
assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
|
||||
return Cursor.ReadVBR64((unsigned)Op.getEncodingData());
|
||||
case BitCodeAbbrevOp::Char6:
|
||||
return BitCodeAbbrevOp::DecodeChar6(Cursor.Read(6));
|
||||
if (Expected<unsigned> Res = Cursor.Read(6))
|
||||
return BitCodeAbbrevOp::DecodeChar6(Res.get());
|
||||
else
|
||||
return Res.takeError();
|
||||
}
|
||||
llvm_unreachable("invalid abbreviation encoding");
|
||||
}
|
||||
|
||||
static void skipAbbreviatedField(BitstreamCursor &Cursor,
|
||||
const BitCodeAbbrevOp &Op) {
|
||||
static Error skipAbbreviatedField(BitstreamCursor &Cursor,
|
||||
const BitCodeAbbrevOp &Op) {
|
||||
assert(!Op.isLiteral() && "Not to be used with literals!");
|
||||
|
||||
// Decode the value as we are commanded.
|
||||
|
@ -79,26 +99,43 @@ static void skipAbbreviatedField(BitstreamCursor &Cursor,
|
|||
llvm_unreachable("Should not reach here");
|
||||
case BitCodeAbbrevOp::Fixed:
|
||||
assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
|
||||
Cursor.Read((unsigned)Op.getEncodingData());
|
||||
break;
|
||||
if (Expected<unsigned> Res = Cursor.Read((unsigned)Op.getEncodingData()))
|
||||
break;
|
||||
else
|
||||
return Res.takeError();
|
||||
case BitCodeAbbrevOp::VBR:
|
||||
assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
|
||||
Cursor.ReadVBR64((unsigned)Op.getEncodingData());
|
||||
break;
|
||||
if (Expected<uint64_t> Res =
|
||||
Cursor.ReadVBR64((unsigned)Op.getEncodingData()))
|
||||
break;
|
||||
else
|
||||
return Res.takeError();
|
||||
case BitCodeAbbrevOp::Char6:
|
||||
Cursor.Read(6);
|
||||
break;
|
||||
if (Expected<unsigned> Res = Cursor.Read(6))
|
||||
break;
|
||||
else
|
||||
return Res.takeError();
|
||||
}
|
||||
return ErrorSuccess();
|
||||
}
|
||||
|
||||
/// skipRecord - Read the current record and discard it.
|
||||
unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) {
|
||||
Expected<unsigned> BitstreamCursor::skipRecord(unsigned AbbrevID) {
|
||||
// Skip unabbreviated records by reading past their entries.
|
||||
if (AbbrevID == bitc::UNABBREV_RECORD) {
|
||||
unsigned Code = ReadVBR(6);
|
||||
unsigned NumElts = ReadVBR(6);
|
||||
Expected<uint32_t> MaybeCode = ReadVBR(6);
|
||||
if (!MaybeCode)
|
||||
return MaybeCode.takeError();
|
||||
unsigned Code = MaybeCode.get();
|
||||
Expected<uint32_t> MaybeVBR = ReadVBR(6);
|
||||
if (!MaybeVBR)
|
||||
return MaybeVBR.get();
|
||||
unsigned NumElts = MaybeVBR.get();
|
||||
for (unsigned i = 0; i != NumElts; ++i)
|
||||
(void)ReadVBR64(6);
|
||||
if (Expected<uint64_t> Res = ReadVBR64(6))
|
||||
; // Skip!
|
||||
else
|
||||
return Res.takeError();
|
||||
return Code;
|
||||
}
|
||||
|
||||
|
@ -110,8 +147,13 @@ unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) {
|
|||
else {
|
||||
if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array ||
|
||||
CodeOp.getEncoding() == BitCodeAbbrevOp::Blob)
|
||||
report_fatal_error("Abbreviation starts with an Array or a Blob");
|
||||
Code = readAbbreviatedField(*this, CodeOp);
|
||||
return llvm::createStringError(
|
||||
std::errc::illegal_byte_sequence,
|
||||
"Abbreviation starts with an Array or a Blob");
|
||||
Expected<uint64_t> MaybeCode = readAbbreviatedField(*this, CodeOp);
|
||||
if (!MaybeCode)
|
||||
return MaybeCode.takeError();
|
||||
Code = MaybeCode.get();
|
||||
}
|
||||
|
||||
for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i < e; ++i) {
|
||||
|
@ -121,13 +163,17 @@ unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) {
|
|||
|
||||
if (Op.getEncoding() != BitCodeAbbrevOp::Array &&
|
||||
Op.getEncoding() != BitCodeAbbrevOp::Blob) {
|
||||
skipAbbreviatedField(*this, Op);
|
||||
if (Error Err = skipAbbreviatedField(*this, Op))
|
||||
return std::move(Err);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
|
||||
// Array case. Read the number of elements as a vbr6.
|
||||
unsigned NumElts = ReadVBR(6);
|
||||
Expected<uint32_t> MaybeNum = ReadVBR(6);
|
||||
if (!MaybeNum)
|
||||
return MaybeNum.takeError();
|
||||
unsigned NumElts = MaybeNum.get();
|
||||
|
||||
// Get the element encoding.
|
||||
assert(i+2 == e && "array op not second to last?");
|
||||
|
@ -140,15 +186,22 @@ unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) {
|
|||
report_fatal_error("Array element type can't be an Array or a Blob");
|
||||
case BitCodeAbbrevOp::Fixed:
|
||||
assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize);
|
||||
JumpToBit(GetCurrentBitNo() + NumElts * EltEnc.getEncodingData());
|
||||
if (Error Err = JumpToBit(GetCurrentBitNo() +
|
||||
NumElts * EltEnc.getEncodingData()))
|
||||
return std::move(Err);
|
||||
break;
|
||||
case BitCodeAbbrevOp::VBR:
|
||||
assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize);
|
||||
for (; NumElts; --NumElts)
|
||||
ReadVBR64((unsigned)EltEnc.getEncodingData());
|
||||
if (Expected<uint64_t> Res =
|
||||
ReadVBR64((unsigned)EltEnc.getEncodingData()))
|
||||
; // Skip!
|
||||
else
|
||||
return Res.takeError();
|
||||
break;
|
||||
case BitCodeAbbrevOp::Char6:
|
||||
JumpToBit(GetCurrentBitNo() + NumElts * 6);
|
||||
if (Error Err = JumpToBit(GetCurrentBitNo() + NumElts * 6))
|
||||
return std::move(Err);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
@ -156,7 +209,10 @@ unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) {
|
|||
|
||||
assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);
|
||||
// Blob case. Read the number of bytes as a vbr6.
|
||||
unsigned NumElts = ReadVBR(6);
|
||||
Expected<uint32_t> MaybeNum = ReadVBR(6);
|
||||
if (!MaybeNum)
|
||||
return MaybeNum.takeError();
|
||||
unsigned NumElts = MaybeNum.get();
|
||||
SkipToFourByteBoundary(); // 32-bit alignment
|
||||
|
||||
// Figure out where the end of this blob will be including tail padding.
|
||||
|
@ -170,19 +226,30 @@ unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) {
|
|||
}
|
||||
|
||||
// Skip over the blob.
|
||||
JumpToBit(NewEnd);
|
||||
if (Error Err = JumpToBit(NewEnd))
|
||||
return std::move(Err);
|
||||
}
|
||||
return Code;
|
||||
}
|
||||
|
||||
unsigned BitstreamCursor::readRecord(unsigned AbbrevID,
|
||||
SmallVectorImpl<uint64_t> &Vals,
|
||||
StringRef *Blob) {
|
||||
Expected<unsigned> BitstreamCursor::readRecord(unsigned AbbrevID,
|
||||
SmallVectorImpl<uint64_t> &Vals,
|
||||
StringRef *Blob) {
|
||||
if (AbbrevID == bitc::UNABBREV_RECORD) {
|
||||
unsigned Code = ReadVBR(6);
|
||||
unsigned NumElts = ReadVBR(6);
|
||||
Expected<uint32_t> MaybeCode = ReadVBR(6);
|
||||
if (!MaybeCode)
|
||||
return MaybeCode.takeError();
|
||||
uint32_t Code = MaybeCode.get();
|
||||
Expected<uint32_t> MaybeNumElts = ReadVBR(6);
|
||||
if (!MaybeNumElts)
|
||||
return MaybeNumElts.takeError();
|
||||
uint32_t NumElts = MaybeNumElts.get();
|
||||
|
||||
for (unsigned i = 0; i != NumElts; ++i)
|
||||
Vals.push_back(ReadVBR64(6));
|
||||
if (Expected<uint64_t> MaybeVal = ReadVBR64(6))
|
||||
Vals.push_back(MaybeVal.get());
|
||||
else
|
||||
return MaybeVal.takeError();
|
||||
return Code;
|
||||
}
|
||||
|
||||
|
@ -198,7 +265,10 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID,
|
|||
if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array ||
|
||||
CodeOp.getEncoding() == BitCodeAbbrevOp::Blob)
|
||||
report_fatal_error("Abbreviation starts with an Array or a Blob");
|
||||
Code = readAbbreviatedField(*this, CodeOp);
|
||||
if (Expected<uint64_t> MaybeCode = readAbbreviatedField(*this, CodeOp))
|
||||
Code = MaybeCode.get();
|
||||
else
|
||||
return MaybeCode.takeError();
|
||||
}
|
||||
|
||||
for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) {
|
||||
|
@ -210,13 +280,19 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID,
|
|||
|
||||
if (Op.getEncoding() != BitCodeAbbrevOp::Array &&
|
||||
Op.getEncoding() != BitCodeAbbrevOp::Blob) {
|
||||
Vals.push_back(readAbbreviatedField(*this, Op));
|
||||
if (Expected<uint64_t> MaybeVal = readAbbreviatedField(*this, Op))
|
||||
Vals.push_back(MaybeVal.get());
|
||||
else
|
||||
return MaybeVal.takeError();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
|
||||
// Array case. Read the number of elements as a vbr6.
|
||||
unsigned NumElts = ReadVBR(6);
|
||||
Expected<uint32_t> MaybeNumElts = ReadVBR(6);
|
||||
if (!MaybeNumElts)
|
||||
return MaybeNumElts.takeError();
|
||||
uint32_t NumElts = MaybeNumElts.get();
|
||||
|
||||
// Get the element encoding.
|
||||
if (i + 2 != e)
|
||||
|
@ -232,22 +308,36 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID,
|
|||
report_fatal_error("Array element type can't be an Array or a Blob");
|
||||
case BitCodeAbbrevOp::Fixed:
|
||||
for (; NumElts; --NumElts)
|
||||
Vals.push_back(Read((unsigned)EltEnc.getEncodingData()));
|
||||
if (Expected<SimpleBitstreamCursor::word_t> MaybeVal =
|
||||
Read((unsigned)EltEnc.getEncodingData()))
|
||||
Vals.push_back(MaybeVal.get());
|
||||
else
|
||||
return MaybeVal.takeError();
|
||||
break;
|
||||
case BitCodeAbbrevOp::VBR:
|
||||
for (; NumElts; --NumElts)
|
||||
Vals.push_back(ReadVBR64((unsigned)EltEnc.getEncodingData()));
|
||||
if (Expected<uint64_t> MaybeVal =
|
||||
ReadVBR64((unsigned)EltEnc.getEncodingData()))
|
||||
Vals.push_back(MaybeVal.get());
|
||||
else
|
||||
return MaybeVal.takeError();
|
||||
break;
|
||||
case BitCodeAbbrevOp::Char6:
|
||||
for (; NumElts; --NumElts)
|
||||
Vals.push_back(BitCodeAbbrevOp::DecodeChar6(Read(6)));
|
||||
if (Expected<SimpleBitstreamCursor::word_t> MaybeVal = Read(6))
|
||||
Vals.push_back(BitCodeAbbrevOp::DecodeChar6(MaybeVal.get()));
|
||||
else
|
||||
return MaybeVal.takeError();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);
|
||||
// Blob case. Read the number of bytes as a vbr6.
|
||||
unsigned NumElts = ReadVBR(6);
|
||||
Expected<uint32_t> MaybeNumElts = ReadVBR(6);
|
||||
if (!MaybeNumElts)
|
||||
return MaybeNumElts.takeError();
|
||||
uint32_t NumElts = MaybeNumElts.get();
|
||||
SkipToFourByteBoundary(); // 32-bit alignment
|
||||
|
||||
// Figure out where the end of this blob will be including tail padding.
|
||||
|
@ -265,7 +355,8 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID,
|
|||
// Otherwise, inform the streamer that we need these bytes in memory. Skip
|
||||
// over tail padding first, in case jumping to NewEnd invalidates the Blob
|
||||
// pointer.
|
||||
JumpToBit(NewEnd);
|
||||
if (Error Err = JumpToBit(NewEnd))
|
||||
return std::move(Err);
|
||||
const char *Ptr = (const char *)getPointerToBit(CurBitPos, NumElts);
|
||||
|
||||
// If we can return a reference to the data, do so to avoid copying it.
|
||||
|
@ -281,19 +372,35 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID,
|
|||
return Code;
|
||||
}
|
||||
|
||||
void BitstreamCursor::ReadAbbrevRecord() {
|
||||
Error BitstreamCursor::ReadAbbrevRecord() {
|
||||
auto Abbv = std::make_shared<BitCodeAbbrev>();
|
||||
unsigned NumOpInfo = ReadVBR(5);
|
||||
Expected<uint32_t> MaybeNumOpInfo = ReadVBR(5);
|
||||
if (!MaybeNumOpInfo)
|
||||
return MaybeNumOpInfo.takeError();
|
||||
unsigned NumOpInfo = MaybeNumOpInfo.get();
|
||||
for (unsigned i = 0; i != NumOpInfo; ++i) {
|
||||
bool IsLiteral = Read(1);
|
||||
Expected<word_t> MaybeIsLiteral = Read(1);
|
||||
if (!MaybeIsLiteral)
|
||||
return MaybeIsLiteral.takeError();
|
||||
bool IsLiteral = MaybeIsLiteral.get();
|
||||
if (IsLiteral) {
|
||||
Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8)));
|
||||
Expected<uint64_t> MaybeOp = ReadVBR64(8);
|
||||
if (!MaybeOp)
|
||||
return MaybeOp.takeError();
|
||||
Abbv->Add(BitCodeAbbrevOp(MaybeOp.get()));
|
||||
continue;
|
||||
}
|
||||
|
||||
BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3);
|
||||
Expected<word_t> MaybeEncoding = Read(3);
|
||||
if (!MaybeEncoding)
|
||||
return MaybeEncoding.takeError();
|
||||
BitCodeAbbrevOp::Encoding E =
|
||||
(BitCodeAbbrevOp::Encoding)MaybeEncoding.get();
|
||||
if (BitCodeAbbrevOp::hasEncodingData(E)) {
|
||||
uint64_t Data = ReadVBR64(5);
|
||||
Expected<uint64_t> MaybeData = ReadVBR64(5);
|
||||
if (!MaybeData)
|
||||
return MaybeData.takeError();
|
||||
uint64_t Data = MaybeData.get();
|
||||
|
||||
// As a special case, handle fixed(0) (i.e., a fixed field with zero bits)
|
||||
// and vbr(0) as a literal zero. This is decoded the same way, and avoids
|
||||
|
@ -317,11 +424,14 @@ void BitstreamCursor::ReadAbbrevRecord() {
|
|||
if (Abbv->getNumOperandInfos() == 0)
|
||||
report_fatal_error("Abbrev record with no operands");
|
||||
CurAbbrevs.push_back(std::move(Abbv));
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Optional<BitstreamBlockInfo>
|
||||
Expected<Optional<BitstreamBlockInfo>>
|
||||
BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {
|
||||
if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return None;
|
||||
if (llvm::Error Err = EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID))
|
||||
return std::move(Err);
|
||||
|
||||
BitstreamBlockInfo NewBlockInfo;
|
||||
|
||||
|
@ -330,7 +440,11 @@ BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {
|
|||
|
||||
// Read all the records for this module.
|
||||
while (true) {
|
||||
BitstreamEntry Entry = advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs);
|
||||
Expected<BitstreamEntry> MaybeEntry =
|
||||
advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs);
|
||||
if (!MaybeEntry)
|
||||
return MaybeEntry.takeError();
|
||||
BitstreamEntry Entry = MaybeEntry.get();
|
||||
|
||||
switch (Entry.Kind) {
|
||||
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
|
||||
|
@ -346,7 +460,8 @@ BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {
|
|||
// Read abbrev records, associate them with CurBID.
|
||||
if (Entry.ID == bitc::DEFINE_ABBREV) {
|
||||
if (!CurBlockInfo) return None;
|
||||
ReadAbbrevRecord();
|
||||
if (Error Err = ReadAbbrevRecord())
|
||||
return std::move(Err);
|
||||
|
||||
// ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the
|
||||
// appropriate BlockInfo.
|
||||
|
@ -357,22 +472,28 @@ BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {
|
|||
|
||||
// Read a record.
|
||||
Record.clear();
|
||||
switch (readRecord(Entry.ID, Record)) {
|
||||
default: break; // Default behavior, ignore unknown content.
|
||||
case bitc::BLOCKINFO_CODE_SETBID:
|
||||
if (Record.size() < 1) return None;
|
||||
CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]);
|
||||
break;
|
||||
case bitc::BLOCKINFO_CODE_BLOCKNAME: {
|
||||
if (!CurBlockInfo) return None;
|
||||
if (!ReadBlockInfoNames)
|
||||
break; // Ignore name.
|
||||
std::string Name;
|
||||
for (unsigned i = 0, e = Record.size(); i != e; ++i)
|
||||
Name += (char)Record[i];
|
||||
CurBlockInfo->Name = Name;
|
||||
break;
|
||||
}
|
||||
Expected<unsigned> MaybeBlockInfo = readRecord(Entry.ID, Record);
|
||||
if (!MaybeBlockInfo)
|
||||
return MaybeBlockInfo.takeError();
|
||||
switch (MaybeBlockInfo.get()) {
|
||||
default:
|
||||
break; // Default behavior, ignore unknown content.
|
||||
case bitc::BLOCKINFO_CODE_SETBID:
|
||||
if (Record.size() < 1)
|
||||
return None;
|
||||
CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]);
|
||||
break;
|
||||
case bitc::BLOCKINFO_CODE_BLOCKNAME: {
|
||||
if (!CurBlockInfo)
|
||||
return None;
|
||||
if (!ReadBlockInfoNames)
|
||||
break; // Ignore name.
|
||||
std::string Name;
|
||||
for (unsigned i = 0, e = Record.size(); i != e; ++i)
|
||||
Name += (char)Record[i];
|
||||
CurBlockInfo->Name = Name;
|
||||
break;
|
||||
}
|
||||
case bitc::BLOCKINFO_CODE_SETRECORDNAME: {
|
||||
if (!CurBlockInfo) return None;
|
||||
if (!ReadBlockInfoNames)
|
||||
|
@ -384,6 +505,6 @@ BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {
|
|||
Name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -674,8 +674,12 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
|
|||
SmallVector<uint64_t, 64> Record;
|
||||
// Get the abbrevs, and preload record positions to make them lazy-loadable.
|
||||
while (true) {
|
||||
BitstreamEntry Entry = IndexCursor.advanceSkippingSubblocks(
|
||||
Expected<BitstreamEntry> MaybeEntry = IndexCursor.advanceSkippingSubblocks(
|
||||
BitstreamCursor::AF_DontPopBlockAtEnd);
|
||||
if (!MaybeEntry)
|
||||
return MaybeEntry.takeError();
|
||||
BitstreamEntry Entry = MaybeEntry.get();
|
||||
|
||||
switch (Entry.Kind) {
|
||||
case BitstreamEntry::SubBlock: // Handled for us already.
|
||||
case BitstreamEntry::Error:
|
||||
|
@ -687,14 +691,22 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
|
|||
// The interesting case.
|
||||
++NumMDRecordLoaded;
|
||||
uint64_t CurrentPos = IndexCursor.GetCurrentBitNo();
|
||||
auto Code = IndexCursor.skipRecord(Entry.ID);
|
||||
Expected<unsigned> MaybeCode = IndexCursor.skipRecord(Entry.ID);
|
||||
if (!MaybeCode)
|
||||
return MaybeCode.takeError();
|
||||
unsigned Code = MaybeCode.get();
|
||||
switch (Code) {
|
||||
case bitc::METADATA_STRINGS: {
|
||||
// Rewind and parse the strings.
|
||||
IndexCursor.JumpToBit(CurrentPos);
|
||||
if (Error Err = IndexCursor.JumpToBit(CurrentPos))
|
||||
return std::move(Err);
|
||||
StringRef Blob;
|
||||
Record.clear();
|
||||
IndexCursor.readRecord(Entry.ID, Record, &Blob);
|
||||
if (Expected<unsigned> MaybeRecord =
|
||||
IndexCursor.readRecord(Entry.ID, Record, &Blob))
|
||||
;
|
||||
else
|
||||
return MaybeRecord.takeError();
|
||||
unsigned NumStrings = Record[0];
|
||||
MDStringRef.reserve(NumStrings);
|
||||
auto IndexNextMDString = [&](StringRef Str) {
|
||||
|
@ -707,26 +719,37 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
|
|||
case bitc::METADATA_INDEX_OFFSET: {
|
||||
// This is the offset to the index, when we see this we skip all the
|
||||
// records and load only an index to these.
|
||||
IndexCursor.JumpToBit(CurrentPos);
|
||||
if (Error Err = IndexCursor.JumpToBit(CurrentPos))
|
||||
return std::move(Err);
|
||||
Record.clear();
|
||||
IndexCursor.readRecord(Entry.ID, Record);
|
||||
if (Expected<unsigned> MaybeRecord =
|
||||
IndexCursor.readRecord(Entry.ID, Record))
|
||||
;
|
||||
else
|
||||
return MaybeRecord.takeError();
|
||||
if (Record.size() != 2)
|
||||
return error("Invalid record");
|
||||
auto Offset = Record[0] + (Record[1] << 32);
|
||||
auto BeginPos = IndexCursor.GetCurrentBitNo();
|
||||
IndexCursor.JumpToBit(BeginPos + Offset);
|
||||
Entry = IndexCursor.advanceSkippingSubblocks(
|
||||
BitstreamCursor::AF_DontPopBlockAtEnd);
|
||||
if (Error Err = IndexCursor.JumpToBit(BeginPos + Offset))
|
||||
return std::move(Err);
|
||||
Expected<BitstreamEntry> MaybeEntry =
|
||||
IndexCursor.advanceSkippingSubblocks(
|
||||
BitstreamCursor::AF_DontPopBlockAtEnd);
|
||||
if (!MaybeEntry)
|
||||
return MaybeEntry.takeError();
|
||||
Entry = MaybeEntry.get();
|
||||
assert(Entry.Kind == BitstreamEntry::Record &&
|
||||
"Corrupted bitcode: Expected `Record` when trying to find the "
|
||||
"Metadata index");
|
||||
Record.clear();
|
||||
auto Code = IndexCursor.readRecord(Entry.ID, Record);
|
||||
(void)Code;
|
||||
assert(Code == bitc::METADATA_INDEX && "Corrupted bitcode: Expected "
|
||||
"`METADATA_INDEX` when trying "
|
||||
"to find the Metadata index");
|
||||
|
||||
if (Expected<unsigned> MaybeCode =
|
||||
IndexCursor.readRecord(Entry.ID, Record))
|
||||
assert(MaybeCode.get() == bitc::METADATA_INDEX &&
|
||||
"Corrupted bitcode: Expected `METADATA_INDEX` when trying to "
|
||||
"find the Metadata index");
|
||||
else
|
||||
return MaybeCode.takeError();
|
||||
// Delta unpack
|
||||
auto CurrentValue = BeginPos;
|
||||
GlobalMetadataBitPosIndex.reserve(Record.size());
|
||||
|
@ -742,21 +765,33 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
|
|||
return error("Corrupted Metadata block");
|
||||
case bitc::METADATA_NAME: {
|
||||
// Named metadata need to be materialized now and aren't deferred.
|
||||
IndexCursor.JumpToBit(CurrentPos);
|
||||
if (Error Err = IndexCursor.JumpToBit(CurrentPos))
|
||||
return std::move(Err);
|
||||
Record.clear();
|
||||
unsigned Code = IndexCursor.readRecord(Entry.ID, Record);
|
||||
assert(Code == bitc::METADATA_NAME);
|
||||
|
||||
unsigned Code;
|
||||
if (Expected<unsigned> MaybeCode =
|
||||
IndexCursor.readRecord(Entry.ID, Record)) {
|
||||
Code = MaybeCode.get();
|
||||
assert(Code == bitc::METADATA_NAME);
|
||||
} else
|
||||
return MaybeCode.takeError();
|
||||
|
||||
// Read name of the named metadata.
|
||||
SmallString<8> Name(Record.begin(), Record.end());
|
||||
Code = IndexCursor.ReadCode();
|
||||
if (Expected<unsigned> MaybeCode = IndexCursor.ReadCode())
|
||||
Code = MaybeCode.get();
|
||||
else
|
||||
return MaybeCode.takeError();
|
||||
|
||||
// Named Metadata comes in two parts, we expect the name to be followed
|
||||
// by the node
|
||||
Record.clear();
|
||||
unsigned NextBitCode = IndexCursor.readRecord(Code, Record);
|
||||
assert(NextBitCode == bitc::METADATA_NAMED_NODE);
|
||||
(void)NextBitCode;
|
||||
if (Expected<unsigned> MaybeNextBitCode =
|
||||
IndexCursor.readRecord(Code, Record))
|
||||
assert(MaybeNextBitCode.get() == bitc::METADATA_NAMED_NODE);
|
||||
else
|
||||
return MaybeNextBitCode.takeError();
|
||||
|
||||
// Read named metadata elements.
|
||||
unsigned Size = Record.size();
|
||||
|
@ -775,9 +810,14 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
|
|||
case bitc::METADATA_GLOBAL_DECL_ATTACHMENT: {
|
||||
// FIXME: we need to do this early because we don't materialize global
|
||||
// value explicitly.
|
||||
IndexCursor.JumpToBit(CurrentPos);
|
||||
if (Error Err = IndexCursor.JumpToBit(CurrentPos))
|
||||
return std::move(Err);
|
||||
Record.clear();
|
||||
IndexCursor.readRecord(Entry.ID, Record);
|
||||
if (Expected<unsigned> MaybeRecord =
|
||||
IndexCursor.readRecord(Entry.ID, Record))
|
||||
;
|
||||
else
|
||||
return MaybeRecord.takeError();
|
||||
if (Record.size() % 2 == 0)
|
||||
return error("Invalid record");
|
||||
unsigned ValueID = Record[0];
|
||||
|
@ -845,8 +885,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
|
|||
// skip the whole block in case we lazy-load.
|
||||
auto EntryPos = Stream.GetCurrentBitNo();
|
||||
|
||||
if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
|
||||
return error("Invalid record");
|
||||
if (Error Err = Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
|
||||
return Err;
|
||||
|
||||
SmallVector<uint64_t, 64> Record;
|
||||
PlaceholderQueue Placeholders;
|
||||
|
@ -871,9 +911,14 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
|
|||
// Return at the beginning of the block, since it is easy to skip it
|
||||
// entirely from there.
|
||||
Stream.ReadBlockEnd(); // Pop the abbrev block context.
|
||||
Stream.JumpToBit(EntryPos);
|
||||
if (Stream.SkipBlock())
|
||||
return error("Invalid record");
|
||||
if (Error Err = IndexCursor.JumpToBit(EntryPos))
|
||||
return Err;
|
||||
if (Error Err = Stream.SkipBlock()) {
|
||||
// FIXME this drops the error on the floor, which
|
||||
// ThinLTO/X86/debuginfo-cu-import.ll relies on.
|
||||
consumeError(std::move(Err));
|
||||
return Error::success();
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
// Couldn't load an index, fallback to loading all the block "old-style".
|
||||
|
@ -883,7 +928,10 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
|
|||
|
||||
// Read all the records.
|
||||
while (true) {
|
||||
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
|
||||
Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
|
||||
if (!MaybeEntry)
|
||||
return MaybeEntry.takeError();
|
||||
BitstreamEntry Entry = MaybeEntry.get();
|
||||
|
||||
switch (Entry.Kind) {
|
||||
case BitstreamEntry::SubBlock: // Handled for us already.
|
||||
|
@ -902,10 +950,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
|
|||
Record.clear();
|
||||
StringRef Blob;
|
||||
++NumMDRecordLoaded;
|
||||
unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob);
|
||||
if (Error Err =
|
||||
parseOneMetadata(Record, Code, Placeholders, Blob, NextMetadataNo))
|
||||
return Err;
|
||||
if (Expected<unsigned> MaybeCode =
|
||||
Stream.readRecord(Entry.ID, Record, &Blob)) {
|
||||
if (Error Err = parseOneMetadata(Record, MaybeCode.get(), Placeholders,
|
||||
Blob, NextMetadataNo))
|
||||
return Err;
|
||||
} else
|
||||
return MaybeCode.takeError();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -930,12 +981,25 @@ void MetadataLoader::MetadataLoaderImpl::lazyLoadOneMetadata(
|
|||
}
|
||||
SmallVector<uint64_t, 64> Record;
|
||||
StringRef Blob;
|
||||
IndexCursor.JumpToBit(GlobalMetadataBitPosIndex[ID - MDStringRef.size()]);
|
||||
auto Entry = IndexCursor.advanceSkippingSubblocks();
|
||||
if (Error Err = IndexCursor.JumpToBit(
|
||||
GlobalMetadataBitPosIndex[ID - MDStringRef.size()]))
|
||||
report_fatal_error("lazyLoadOneMetadata failed jumping: " +
|
||||
toString(std::move(Err)));
|
||||
Expected<BitstreamEntry> MaybeEntry = IndexCursor.advanceSkippingSubblocks();
|
||||
if (!MaybeEntry)
|
||||
// FIXME this drops the error on the floor.
|
||||
report_fatal_error("lazyLoadOneMetadata failed advanceSkippingSubblocks: " +
|
||||
toString(MaybeEntry.takeError()));
|
||||
BitstreamEntry Entry = MaybeEntry.get();
|
||||
++NumMDRecordLoaded;
|
||||
unsigned Code = IndexCursor.readRecord(Entry.ID, Record, &Blob);
|
||||
if (Error Err = parseOneMetadata(Record, Code, Placeholders, Blob, ID))
|
||||
report_fatal_error("Can't lazyload MD");
|
||||
if (Expected<unsigned> MaybeCode =
|
||||
IndexCursor.readRecord(Entry.ID, Record, &Blob)) {
|
||||
if (Error Err =
|
||||
parseOneMetadata(Record, MaybeCode.get(), Placeholders, Blob, ID))
|
||||
report_fatal_error("Can't lazyload MD, parseOneMetadata: " +
|
||||
toString(std::move(Err)));
|
||||
} else
|
||||
report_fatal_error("Can't lazyload MD: " + toString(MaybeCode.takeError()));
|
||||
}
|
||||
|
||||
/// Ensure that all forward-references and placeholders are resolved.
|
||||
|
@ -1032,12 +1096,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
|
|||
// Read name of the named metadata.
|
||||
SmallString<8> Name(Record.begin(), Record.end());
|
||||
Record.clear();
|
||||
Code = Stream.ReadCode();
|
||||
Expected<unsigned> MaybeCode = Stream.ReadCode();
|
||||
if (!MaybeCode)
|
||||
return MaybeCode.takeError();
|
||||
Code = MaybeCode.get();
|
||||
|
||||
++NumMDRecordLoaded;
|
||||
unsigned NextBitCode = Stream.readRecord(Code, Record);
|
||||
if (NextBitCode != bitc::METADATA_NAMED_NODE)
|
||||
return error("METADATA_NAME not followed by METADATA_NAMED_NODE");
|
||||
if (Expected<unsigned> MaybeNextBitCode = Stream.readRecord(Code, Record)) {
|
||||
if (MaybeNextBitCode.get() != bitc::METADATA_NAMED_NODE)
|
||||
return error("METADATA_NAME not followed by METADATA_NAMED_NODE");
|
||||
} else
|
||||
return MaybeNextBitCode.takeError();
|
||||
|
||||
// Read named metadata elements.
|
||||
unsigned Size = Record.size();
|
||||
|
@ -1863,7 +1932,10 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadataStrings(
|
|||
if (R.AtEndOfStream())
|
||||
return error("Invalid record: metadata strings bad length");
|
||||
|
||||
unsigned Size = R.ReadVBR(6);
|
||||
Expected<uint32_t> MaybeSize = R.ReadVBR(6);
|
||||
if (!MaybeSize)
|
||||
return MaybeSize.takeError();
|
||||
uint32_t Size = MaybeSize.get();
|
||||
if (Strings.size() < Size)
|
||||
return error("Invalid record: metadata strings truncated chars");
|
||||
|
||||
|
@ -1892,14 +1964,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseGlobalObjectAttachment(
|
|||
/// Parse metadata attachments.
|
||||
Error MetadataLoader::MetadataLoaderImpl::parseMetadataAttachment(
|
||||
Function &F, const SmallVectorImpl<Instruction *> &InstructionList) {
|
||||
if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
|
||||
return error("Invalid record");
|
||||
if (Error Err = Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
|
||||
return Err;
|
||||
|
||||
SmallVector<uint64_t, 64> Record;
|
||||
PlaceholderQueue Placeholders;
|
||||
|
||||
while (true) {
|
||||
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
|
||||
Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
|
||||
if (!MaybeEntry)
|
||||
return MaybeEntry.takeError();
|
||||
BitstreamEntry Entry = MaybeEntry.get();
|
||||
|
||||
switch (Entry.Kind) {
|
||||
case BitstreamEntry::SubBlock: // Handled for us already.
|
||||
|
@ -1916,7 +1991,10 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadataAttachment(
|
|||
// Read a metadata attachment record.
|
||||
Record.clear();
|
||||
++NumMDRecordLoaded;
|
||||
switch (Stream.readRecord(Entry.ID, Record)) {
|
||||
Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
|
||||
if (!MaybeRecord)
|
||||
return MaybeRecord.takeError();
|
||||
switch (MaybeRecord.get()) {
|
||||
default: // Default behavior: ignore.
|
||||
break;
|
||||
case bitc::METADATA_ATTACHMENT: {
|
||||
|
@ -1990,14 +2068,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadataKindRecord(
|
|||
|
||||
/// Parse the metadata kinds out of the METADATA_KIND_BLOCK.
|
||||
Error MetadataLoader::MetadataLoaderImpl::parseMetadataKinds() {
|
||||
if (Stream.EnterSubBlock(bitc::METADATA_KIND_BLOCK_ID))
|
||||
return error("Invalid record");
|
||||
if (Error Err = Stream.EnterSubBlock(bitc::METADATA_KIND_BLOCK_ID))
|
||||
return Err;
|
||||
|
||||
SmallVector<uint64_t, 64> Record;
|
||||
|
||||
// Read all the records.
|
||||
while (true) {
|
||||
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
|
||||
Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
|
||||
if (!MaybeEntry)
|
||||
return MaybeEntry.takeError();
|
||||
BitstreamEntry Entry = MaybeEntry.get();
|
||||
|
||||
switch (Entry.Kind) {
|
||||
case BitstreamEntry::SubBlock: // Handled for us already.
|
||||
|
@ -2013,8 +2094,10 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadataKinds() {
|
|||
// Read a record.
|
||||
Record.clear();
|
||||
++NumMDRecordLoaded;
|
||||
unsigned Code = Stream.readRecord(Entry.ID, Record);
|
||||
switch (Code) {
|
||||
Expected<unsigned> MaybeCode = Stream.readRecord(Entry.ID, Record);
|
||||
if (!MaybeCode)
|
||||
return MaybeCode.takeError();
|
||||
switch (MaybeCode.get()) {
|
||||
default: // Default behavior: ignore.
|
||||
break;
|
||||
case bitc::METADATA_KIND: {
|
||||
|
|
|
@ -29,13 +29,13 @@ RUN: FileCheck --check-prefix=MISMATCHED-EXPLICIT-INVOKE %s
|
|||
RUN: not llvm-dis -disable-output %p/Inputs/invalid-invoke-non-function-explicit-type.bc 2>&1 | \
|
||||
RUN: FileCheck --check-prefix=NON-FUNCTION-EXPLICIT-INVOKE %s
|
||||
|
||||
INVALID-EMPTY: Invalid bitcode signature
|
||||
INVALID-EMPTY: error: file too small to contain bitcode header
|
||||
INVALID-ENCODING: Invalid encoding
|
||||
BAD-ABBREV: Malformed block
|
||||
UNEXPECTED-EOF: Malformed block
|
||||
BAD-ABBREV-NUMBER: Malformed block
|
||||
BAD-ABBREV: error: can't skip to bit 25870861920 from 96
|
||||
UNEXPECTED-EOF: error: can't skip to bit 25870861920 from 96
|
||||
BAD-ABBREV-NUMBER: error: can't skip to bit 25870861920 from 96
|
||||
BAD-TYPE-TABLE-FORWARD-REF: Invalid TYPE table: Only named structs can be forward referenced
|
||||
BAD-BITWIDTH: Malformed block
|
||||
BAD-BITWIDTH: error: can't skip to bit 3616 from 96
|
||||
BAD-ALIGN: Invalid alignment value
|
||||
MISMATCHED-EXPLICIT-GEP: Explicit gep type does not match pointee type of pointer operand
|
||||
MISMATCHED-EXPLICIT-LOAD: Explicit load/store type does not match pointee type of pointer operand
|
||||
|
@ -154,7 +154,7 @@ EXTRACT-0-IDXS: EXTRACTVAL: Invalid instruction with 0 indices
|
|||
RUN: not llvm-dis -disable-output %p/Inputs/invalid-load-ptr-type.bc 2>&1 | \
|
||||
RUN: FileCheck --check-prefix=BAD-LOAD-PTR-TYPE %s
|
||||
|
||||
BAD-LOAD-PTR-TYPE: Malformed block
|
||||
BAD-LOAD-PTR-TYPE: error: can't skip to bit 3616 from 96
|
||||
|
||||
RUN: not llvm-dis -disable-output %p/Inputs/invalid-inserted-value-type-mismatch.bc 2>&1 | \
|
||||
RUN: FileCheck --check-prefix=INSERT-TYPE-MISMATCH %s
|
||||
|
@ -164,7 +164,7 @@ INSERT-TYPE-MISMATCH: Inserted value type doesn't match aggregate type
|
|||
RUN: not llvm-dis -disable-output %p/Inputs/invalid-code-len-width.bc 2>&1 | \
|
||||
RUN: FileCheck --check-prefix=INVALID-CODELENWIDTH %s
|
||||
|
||||
INVALID-CODELENWIDTH: Malformed block
|
||||
INVALID-CODELENWIDTH: error: can't skip to bit 3616 from 96
|
||||
|
||||
RUN: not llvm-dis -disable-output %p/Inputs/invalid-function-argument-type.bc 2>&1 | \
|
||||
RUN: FileCheck --check-prefix=INVALID-ARGUMENT-TYPE %s
|
||||
|
|
|
@ -8,4 +8,4 @@
|
|||
; CHECK-LIBS: llvm-lto: {{.*}}/Inputs/empty.bc: Could not read LTO input file: The file was not recognized as a valid object file
|
||||
|
||||
; RUN: not llvm-lto --thinlto %S/Inputs/empty.bc 2>&1 | FileCheck %s --check-prefix=CHECK-THIN
|
||||
; CHECK-THIN: llvm-lto: error loading file '{{.*}}/Inputs/empty.bc': Invalid bitcode signature
|
||||
; CHECK-THIN: llvm-lto: error loading file '{{.*}}/Inputs/empty.bc': file too small to contain bitcode header
|
||||
|
|
|
@ -449,15 +449,17 @@ struct PerBlockIDStats {
|
|||
|
||||
static std::map<unsigned, PerBlockIDStats> BlockIDStats;
|
||||
|
||||
|
||||
|
||||
/// ReportError - All bitcode analysis errors go through this function, making this a
|
||||
/// good place to breakpoint if debugging.
|
||||
/// All bitcode analysis errors go through this function, making this a good
|
||||
/// place to breakpoint if debugging.
|
||||
static bool ReportError(const Twine &Err) {
|
||||
WithColor::error() << Err << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ReportError(Error &&Err) {
|
||||
return ReportError(toString(std::move(Err)));
|
||||
}
|
||||
|
||||
static bool decodeMetadataStringsBlob(StringRef Indent,
|
||||
ArrayRef<uint64_t> Record,
|
||||
StringRef Blob) {
|
||||
|
@ -478,7 +480,10 @@ static bool decodeMetadataStringsBlob(StringRef Indent,
|
|||
if (R.AtEndOfStream())
|
||||
return ReportError("bad length");
|
||||
|
||||
unsigned Size = R.ReadVBR(6);
|
||||
Expected<uint32_t> MaybeSize = R.ReadVBR(6);
|
||||
if (!MaybeSize)
|
||||
return ReportError(MaybeSize.takeError());
|
||||
uint32_t Size = MaybeSize.get();
|
||||
if (Strings.size() < Size)
|
||||
return ReportError("truncated chars");
|
||||
|
||||
|
@ -518,19 +523,24 @@ static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo,
|
|||
bool DumpRecords = Dump;
|
||||
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
|
||||
if (Dump) outs() << Indent << "<BLOCKINFO_BLOCK/>\n";
|
||||
Optional<BitstreamBlockInfo> NewBlockInfo =
|
||||
Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
|
||||
Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
|
||||
if (!MaybeNewBlockInfo)
|
||||
return ReportError(MaybeNewBlockInfo.takeError());
|
||||
Optional<BitstreamBlockInfo> NewBlockInfo =
|
||||
std::move(MaybeNewBlockInfo.get());
|
||||
if (!NewBlockInfo)
|
||||
return ReportError("Malformed BlockInfoBlock");
|
||||
BlockInfo = std::move(*NewBlockInfo);
|
||||
Stream.JumpToBit(BlockBitStart);
|
||||
if (Error Err = Stream.JumpToBit(BlockBitStart))
|
||||
return ReportError(std::move(Err));
|
||||
// It's not really interesting to dump the contents of the blockinfo block.
|
||||
DumpRecords = false;
|
||||
}
|
||||
|
||||
unsigned NumWords = 0;
|
||||
if (Stream.EnterSubBlock(BlockID, &NumWords))
|
||||
return ReportError("Malformed block record");
|
||||
if (Error Err = Stream.EnterSubBlock(BlockID, &NumWords))
|
||||
return ReportError(std::move(Err));
|
||||
|
||||
// Keep it for later, when we see a MODULE_HASH record
|
||||
uint64_t BlockEntryPos = Stream.getCurrentByteNo();
|
||||
|
@ -562,9 +572,12 @@ static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo,
|
|||
|
||||
uint64_t RecordStartBit = Stream.GetCurrentBitNo();
|
||||
|
||||
BitstreamEntry Entry =
|
||||
Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
|
||||
|
||||
Expected<BitstreamEntry> MaybeEntry =
|
||||
Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
|
||||
if (!MaybeEntry)
|
||||
return ReportError(MaybeEntry.takeError());
|
||||
BitstreamEntry Entry = MaybeEntry.get();
|
||||
|
||||
switch (Entry.Kind) {
|
||||
case BitstreamEntry::Error:
|
||||
return ReportError("malformed bitcode file");
|
||||
|
@ -599,7 +612,8 @@ static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo,
|
|||
}
|
||||
|
||||
if (Entry.ID == bitc::DEFINE_ABBREV) {
|
||||
Stream.ReadAbbrevRecord();
|
||||
if (Error Err = Stream.ReadAbbrevRecord())
|
||||
return ReportError(std::move(Err));
|
||||
++BlockStats.NumAbbrevs;
|
||||
continue;
|
||||
}
|
||||
|
@ -610,7 +624,10 @@ static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo,
|
|||
|
||||
StringRef Blob;
|
||||
uint64_t CurrentRecordPos = Stream.GetCurrentBitNo();
|
||||
unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob);
|
||||
Expected<unsigned> MaybeCode = Stream.readRecord(Entry.ID, Record, &Blob);
|
||||
if (!MaybeCode)
|
||||
return ReportError(MaybeCode.takeError());
|
||||
unsigned Code = MaybeCode.get();
|
||||
|
||||
// Increment the # occurrences of this code.
|
||||
if (BlockStats.CodeFreq.size() <= Code)
|
||||
|
@ -742,8 +759,12 @@ static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo,
|
|||
}
|
||||
|
||||
// Make sure that we can skip the current record.
|
||||
Stream.JumpToBit(CurrentRecordPos);
|
||||
Stream.skipRecord(Entry.ID);
|
||||
if (Error Err = Stream.JumpToBit(CurrentRecordPos))
|
||||
return ReportError(std::move(Err));
|
||||
if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID))
|
||||
; // Do nothing.
|
||||
else
|
||||
return ReportError(Skipped.takeError());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -755,27 +776,45 @@ static void PrintSize(uint64_t Bits) {
|
|||
(double)Bits/8, (unsigned long)(Bits/32));
|
||||
}
|
||||
|
||||
static CurStreamTypeType ReadSignature(BitstreamCursor &Stream) {
|
||||
static Expected<CurStreamTypeType> ReadSignature(BitstreamCursor &Stream) {
|
||||
auto tryRead = [&Stream](char &Dest, size_t size) -> Error {
|
||||
if (Expected<SimpleBitstreamCursor::word_t> MaybeWord = Stream.Read(size))
|
||||
Dest = MaybeWord.get();
|
||||
else
|
||||
return MaybeWord.takeError();
|
||||
return Error::success();
|
||||
};
|
||||
|
||||
char Signature[6];
|
||||
Signature[0] = Stream.Read(8);
|
||||
Signature[1] = Stream.Read(8);
|
||||
if (Error Err = tryRead(Signature[0], 8))
|
||||
return std::move(Err);
|
||||
if (Error Err = tryRead(Signature[1], 8))
|
||||
return std::move(Err);
|
||||
|
||||
// Autodetect the file contents, if it is one we know.
|
||||
if (Signature[0] == 'C' && Signature[1] == 'P') {
|
||||
Signature[2] = Stream.Read(8);
|
||||
Signature[3] = Stream.Read(8);
|
||||
if (Error Err = tryRead(Signature[2], 8))
|
||||
return std::move(Err);
|
||||
if (Error Err = tryRead(Signature[3], 8))
|
||||
return std::move(Err);
|
||||
if (Signature[2] == 'C' && Signature[3] == 'H')
|
||||
return ClangSerializedASTBitstream;
|
||||
} else if (Signature[0] == 'D' && Signature[1] == 'I') {
|
||||
Signature[2] = Stream.Read(8);
|
||||
Signature[3] = Stream.Read(8);
|
||||
if (Error Err = tryRead(Signature[2], 8))
|
||||
return std::move(Err);
|
||||
if (Error Err = tryRead(Signature[3], 8))
|
||||
return std::move(Err);
|
||||
if (Signature[2] == 'A' && Signature[3] == 'G')
|
||||
return ClangSerializedDiagnosticsBitstream;
|
||||
} else {
|
||||
Signature[2] = Stream.Read(4);
|
||||
Signature[3] = Stream.Read(4);
|
||||
Signature[4] = Stream.Read(4);
|
||||
Signature[5] = Stream.Read(4);
|
||||
if (Error Err = tryRead(Signature[2], 4))
|
||||
return std::move(Err);
|
||||
if (Error Err = tryRead(Signature[3], 4))
|
||||
return std::move(Err);
|
||||
if (Error Err = tryRead(Signature[4], 4))
|
||||
return std::move(Err);
|
||||
if (Error Err = tryRead(Signature[5], 4))
|
||||
return std::move(Err);
|
||||
if (Signature[0] == 'B' && Signature[1] == 'C' &&
|
||||
Signature[2] == 0x0 && Signature[3] == 0xC &&
|
||||
Signature[4] == 0xE && Signature[5] == 0xD)
|
||||
|
@ -827,7 +866,10 @@ static bool openBitcodeFile(StringRef Path,
|
|||
}
|
||||
|
||||
Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr));
|
||||
CurStreamType = ReadSignature(Stream);
|
||||
Expected<CurStreamTypeType> MaybeSignature = ReadSignature(Stream);
|
||||
if (!MaybeSignature)
|
||||
return ReportError(MaybeSignature.takeError());
|
||||
CurStreamType = std::move(MaybeSignature.get());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -853,21 +895,30 @@ static int AnalyzeBitcode() {
|
|||
return true;
|
||||
|
||||
while (!BlockInfoCursor.AtEndOfStream()) {
|
||||
unsigned Code = BlockInfoCursor.ReadCode();
|
||||
if (Code != bitc::ENTER_SUBBLOCK)
|
||||
Expected<unsigned> MaybeCode = BlockInfoCursor.ReadCode();
|
||||
if (!MaybeCode)
|
||||
return ReportError(MaybeCode.takeError());
|
||||
if (MaybeCode.get() != bitc::ENTER_SUBBLOCK)
|
||||
return ReportError("Invalid record at top-level in block info file");
|
||||
|
||||
unsigned BlockID = BlockInfoCursor.ReadSubBlockID();
|
||||
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
|
||||
Optional<BitstreamBlockInfo> NewBlockInfo =
|
||||
Expected<unsigned> MaybeBlockID = BlockInfoCursor.ReadSubBlockID();
|
||||
if (!MaybeBlockID)
|
||||
return ReportError(MaybeBlockID.takeError());
|
||||
if (MaybeBlockID.get() == bitc::BLOCKINFO_BLOCK_ID) {
|
||||
Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
|
||||
BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
|
||||
if (!MaybeNewBlockInfo)
|
||||
return ReportError(MaybeNewBlockInfo.takeError());
|
||||
Optional<BitstreamBlockInfo> NewBlockInfo =
|
||||
std::move(MaybeNewBlockInfo.get());
|
||||
if (!NewBlockInfo)
|
||||
return ReportError("Malformed BlockInfoBlock in block info file");
|
||||
BlockInfo = std::move(*NewBlockInfo);
|
||||
break;
|
||||
}
|
||||
|
||||
BlockInfoCursor.SkipBlock();
|
||||
if (Error Err = BlockInfoCursor.SkipBlock())
|
||||
return ReportError(std::move(Err));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -875,13 +926,17 @@ static int AnalyzeBitcode() {
|
|||
|
||||
// Parse the top-level structure. We only allow blocks at the top-level.
|
||||
while (!Stream.AtEndOfStream()) {
|
||||
unsigned Code = Stream.ReadCode();
|
||||
if (Code != bitc::ENTER_SUBBLOCK)
|
||||
Expected<unsigned> MaybeCode = Stream.ReadCode();
|
||||
if (!MaybeCode)
|
||||
return ReportError(MaybeCode.takeError());
|
||||
if (MaybeCode.get() != bitc::ENTER_SUBBLOCK)
|
||||
return ReportError("Invalid record at top-level");
|
||||
|
||||
unsigned BlockID = Stream.ReadSubBlockID();
|
||||
Expected<unsigned> MaybeBlockID = Stream.ReadSubBlockID();
|
||||
if (!MaybeBlockID)
|
||||
return ReportError(MaybeBlockID.takeError());
|
||||
|
||||
if (ParseBlock(Stream, BlockInfo, BlockID, 0, CurStreamType))
|
||||
if (ParseBlock(Stream, BlockInfo, MaybeBlockID.get(), 0, CurStreamType))
|
||||
return true;
|
||||
++NumTopBlocks;
|
||||
}
|
||||
|
|
|
@ -22,15 +22,17 @@ TEST(BitstreamReaderTest, AtEndOfStream) {
|
|||
BitstreamCursor Cursor(Bytes);
|
||||
|
||||
EXPECT_FALSE(Cursor.AtEndOfStream());
|
||||
(void)Cursor.Read(8);
|
||||
Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8);
|
||||
EXPECT_TRUE((bool)MaybeRead);
|
||||
EXPECT_FALSE(Cursor.AtEndOfStream());
|
||||
(void)Cursor.Read(24);
|
||||
MaybeRead = Cursor.Read(24);
|
||||
EXPECT_TRUE((bool)MaybeRead);
|
||||
EXPECT_TRUE(Cursor.AtEndOfStream());
|
||||
|
||||
Cursor.JumpToBit(0);
|
||||
EXPECT_FALSE(Cursor.JumpToBit(0));
|
||||
EXPECT_FALSE(Cursor.AtEndOfStream());
|
||||
|
||||
Cursor.JumpToBit(32);
|
||||
EXPECT_FALSE(Cursor.JumpToBit(32));
|
||||
EXPECT_TRUE(Cursor.AtEndOfStream());
|
||||
}
|
||||
|
||||
|
@ -40,7 +42,7 @@ TEST(BitstreamReaderTest, AtEndOfStreamJump) {
|
|||
};
|
||||
BitstreamCursor Cursor(Bytes);
|
||||
|
||||
Cursor.JumpToBit(32);
|
||||
EXPECT_FALSE(Cursor.JumpToBit(32));
|
||||
EXPECT_TRUE(Cursor.AtEndOfStream());
|
||||
}
|
||||
|
||||
|
@ -56,7 +58,8 @@ TEST(BitstreamReaderTest, getCurrentByteNo) {
|
|||
|
||||
for (unsigned I = 0, E = 32; I != E; ++I) {
|
||||
EXPECT_EQ(I / 8, Cursor.getCurrentByteNo());
|
||||
(void)Cursor.Read(1);
|
||||
Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(1);
|
||||
EXPECT_TRUE((bool)MaybeRead);
|
||||
}
|
||||
EXPECT_EQ(4u, Cursor.getCurrentByteNo());
|
||||
}
|
||||
|
@ -116,24 +119,33 @@ TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
|
|||
|
||||
// Header. Included in test so that we can run llvm-bcanalyzer to debug
|
||||
// when there are problems.
|
||||
ASSERT_EQ(Magic, Stream.Read(32));
|
||||
Expected<SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(32);
|
||||
ASSERT_TRUE((bool)MaybeRead);
|
||||
ASSERT_EQ(Magic, MaybeRead.get());
|
||||
|
||||
// Block.
|
||||
BitstreamEntry Entry =
|
||||
Expected<BitstreamEntry> MaybeEntry =
|
||||
Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
|
||||
ASSERT_TRUE((bool)MaybeEntry);
|
||||
BitstreamEntry Entry = MaybeEntry.get();
|
||||
ASSERT_EQ(BitstreamEntry::SubBlock, Entry.Kind);
|
||||
ASSERT_EQ(BlockID, Entry.ID);
|
||||
ASSERT_FALSE(Stream.EnterSubBlock(BlockID));
|
||||
|
||||
// Abbreviation.
|
||||
Entry = Stream.advance();
|
||||
MaybeEntry = Stream.advance();
|
||||
ASSERT_TRUE((bool)MaybeEntry);
|
||||
Entry = MaybeEntry.get();
|
||||
ASSERT_EQ(BitstreamEntry::Record, Entry.Kind);
|
||||
ASSERT_EQ(AbbrevID, Entry.ID);
|
||||
|
||||
// Record.
|
||||
StringRef BlobOut;
|
||||
SmallVector<uint64_t, 1> Record;
|
||||
ASSERT_EQ(RecordID, Stream.readRecord(Entry.ID, Record, &BlobOut));
|
||||
Expected<unsigned> MaybeRecord =
|
||||
Stream.readRecord(Entry.ID, Record, &BlobOut);
|
||||
ASSERT_TRUE((bool)MaybeRecord);
|
||||
ASSERT_EQ(RecordID, MaybeRecord.get());
|
||||
EXPECT_TRUE(Record.empty());
|
||||
EXPECT_EQ(BlobIn, BlobOut);
|
||||
}
|
||||
|
@ -143,7 +155,9 @@ TEST(BitstreamReaderTest, shortRead) {
|
|||
uint8_t Bytes[] = {8, 7, 6, 5, 4, 3, 2, 1};
|
||||
for (unsigned I = 1; I != 8; ++I) {
|
||||
SimpleBitstreamCursor Cursor(ArrayRef<uint8_t>(Bytes, I));
|
||||
EXPECT_EQ(8ull, Cursor.Read(8));
|
||||
Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8);
|
||||
ASSERT_TRUE((bool)MaybeRead);
|
||||
EXPECT_EQ(8ull, MaybeRead.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue