| Index: lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
|
| diff --git a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
|
| index 0d6f818d6bcef2d9cdb3269590556e7be1af64d8..ab3868e3fa7d54666f4cc10eaf9badac8f481b37 100644
|
| --- a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
|
| +++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
|
| @@ -116,6 +116,48 @@ bool NaClBitcodeReaderValueList::createValueFwdRef(unsigned Idx, Type *Ty) {
|
| return false;
|
| }
|
|
|
| +namespace {
|
| +class NaClBitcodeErrorCategoryType : public std::error_category {
|
| + const char *name() const LLVM_NOEXCEPT override {
|
| + return "pnacl.bitcode";
|
| + }
|
| + std::string message(int IndexError) const override {
|
| + switch(static_cast<NaClBitcodeReader::ErrorType>(IndexError)) {
|
| + case NaClBitcodeReader::CouldNotFindFunctionInStream:
|
| + return "Unable to find function in bitcode stream.";
|
| + case NaClBitcodeReader::InsufficientFunctionProtos:
|
| + return "Insufficient function protos";
|
| + case NaClBitcodeReader::InvalidBitstream:
|
| + return "Error in bitstream format";
|
| + case NaClBitcodeReader::InvalidConstantReference:
|
| + return "Bad constant reference";
|
| + case NaClBitcodeReader::InvalidInstructionWithNoBB:
|
| + return "No basic block for instruction";
|
| + case NaClBitcodeReader::InvalidMultipleBlocks:
|
| + return "Multiple blocks for a kind of block that should have only one";
|
| + case NaClBitcodeReader::InvalidRecord:
|
| + return "Record doesn't have expected size or structure";
|
| + case NaClBitcodeReader::InvalidSkippedBlock:
|
| + return "Unable to skip unknown block in bitcode file";
|
| + case NaClBitcodeReader::InvalidType:
|
| + return "Invalid type in record";
|
| + case NaClBitcodeReader::InvalidTypeForValue:
|
| + return "Type of value in record incorrect";
|
| + case NaClBitcodeReader::InvalidValue:
|
| + return "Invalid value in record";
|
| + case NaClBitcodeReader::MalformedBlock:
|
| + return "Malformed block. Unable to advance over block";
|
| + }
|
| + llvm_unreachable("Unknown error type!");
|
| + }
|
| +};
|
| +} // end of anonomous namespace.
|
| +
|
| +const std::error_category &NaClBitcodeReader::BitcodeErrorCategory() {
|
| + static NaClBitcodeErrorCategoryType ErrCat;
|
| + return ErrCat;
|
| +}
|
| +
|
| Type *NaClBitcodeReader::getTypeByID(unsigned ID) {
|
| // The type table size is always specified correctly.
|
| if (ID >= TypeList.size())
|
| @@ -135,20 +177,27 @@ Type *NaClBitcodeReader::getTypeByID(unsigned ID) {
|
| //===----------------------------------------------------------------------===//
|
|
|
|
|
| -bool NaClBitcodeReader::ParseTypeTable() {
|
| +std::error_code NaClBitcodeReader::Error(ErrorType E,
|
| + const std::string &Message) const {
|
| + if (Verbose)
|
| + *Verbose << "Error: " << Message << "\n";
|
| + return Error(E);
|
| +}
|
| +
|
| +std::error_code NaClBitcodeReader::ParseTypeTable() {
|
| DEBUG(dbgs() << "-> ParseTypeTable\n");
|
| if (Stream.EnterSubBlock(naclbitc::TYPE_BLOCK_ID_NEW))
|
| - return Error("Malformed block record");
|
| + return Error(InvalidRecord, "Malformed block record");
|
|
|
| - bool result = ParseTypeTableBody();
|
| + std::error_code result = ParseTypeTableBody();
|
| if (!result)
|
| DEBUG(dbgs() << "<- ParseTypeTable\n");
|
| return result;
|
| }
|
|
|
| -bool NaClBitcodeReader::ParseTypeTableBody() {
|
| +std::error_code NaClBitcodeReader::ParseTypeTableBody() {
|
| if (!TypeList.empty())
|
| - return Error("Multiple TYPE_BLOCKs found!");
|
| + return Error(InvalidMultipleBlocks, "Multiple TYPE_BLOCKs found!");
|
|
|
| SmallVector<uint64_t, 64> Record;
|
| unsigned NumRecords = 0;
|
| @@ -160,12 +209,12 @@ bool NaClBitcodeReader::ParseTypeTableBody() {
|
| switch (Entry.Kind) {
|
| case NaClBitstreamEntry::SubBlock: // Handled for us already.
|
| case NaClBitstreamEntry::Error:
|
| - Error("Error in the type table block");
|
| - return true;
|
| + return Error(MalformedBlock, "Error in the type table block");
|
| case NaClBitstreamEntry::EndBlock:
|
| if (NumRecords != TypeList.size())
|
| - return Error("Invalid type forward reference in TYPE_BLOCK");
|
| - return false;
|
| + return Error(MalformedBlock,
|
| + "Invalid type forward reference in TYPE_BLOCK");
|
| + return std::error_code();
|
| case NaClBitstreamEntry::Record:
|
| // The interesting case.
|
| break;
|
| @@ -181,46 +230,46 @@ bool NaClBitcodeReader::ParseTypeTableBody() {
|
| raw_string_ostream StrM(Message);
|
| StrM << "Unknown type code in type table: " << TypeCode;
|
| StrM.flush();
|
| - return Error(Message);
|
| + return Error(InvalidValue, Message);
|
| }
|
|
|
| case naclbitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
|
| // TYPE_CODE_NUMENTRY contains a count of the number of types in the
|
| // type list. This allows us to reserve space.
|
| if (Record.size() != 1)
|
| - return Error("Invalid TYPE_CODE_NUMENTRY record");
|
| + return Error(InvalidRecord, "Invalid TYPE_CODE_NUMENTRY record");
|
| TypeList.resize(Record[0]);
|
| // No type was defined, skip the checks that follow the switch.
|
| continue;
|
|
|
| case naclbitc::TYPE_CODE_VOID: // VOID
|
| if (Record.size() != 0)
|
| - return Error("Invalid TYPE_CODE_VOID record");
|
| + return Error(InvalidRecord, "Invalid TYPE_CODE_VOID record");
|
| ResultTy = Type::getVoidTy(Context);
|
| break;
|
|
|
| case naclbitc::TYPE_CODE_FLOAT: // FLOAT
|
| if (Record.size() != 0)
|
| - return Error("Invalid TYPE_CODE_FLOAT record");
|
| + return Error(InvalidRecord, "Invalid TYPE_CODE_FLOAT record");
|
| ResultTy = Type::getFloatTy(Context);
|
| break;
|
|
|
| case naclbitc::TYPE_CODE_DOUBLE: // DOUBLE
|
| if (Record.size() != 0)
|
| - return Error("Invalid TYPE_CODE_DOUBLE record");
|
| + return Error(InvalidRecord, "Invalid TYPE_CODE_DOUBLE record");
|
| ResultTy = Type::getDoubleTy(Context);
|
| break;
|
|
|
| case naclbitc::TYPE_CODE_INTEGER: // INTEGER: [width]
|
| if (Record.size() != 1)
|
| - return Error("Invalid TYPE_CODE_INTEGER record");
|
| + return Error(InvalidRecord, "Invalid TYPE_CODE_INTEGER record");
|
| ResultTy = IntegerType::get(Context, Record[0]);
|
| break;
|
|
|
| case naclbitc::TYPE_CODE_FUNCTION: {
|
| // FUNCTION: [vararg, retty, paramty x N]
|
| if (Record.size() < 2)
|
| - return Error("Invalid TYPE_CODE_FUNCTION record");
|
| + return Error(InvalidRecord, "Invalid TYPE_CODE_FUNCTION record");
|
| SmallVector<Type *, 8> ArgTys;
|
| for (unsigned i = 2, e = Record.size(); i != e; ++i) {
|
| if (Type *T = getTypeByID(Record[i]))
|
| @@ -231,28 +280,29 @@ bool NaClBitcodeReader::ParseTypeTableBody() {
|
|
|
| ResultTy = getTypeByID(Record[1]);
|
| if (ResultTy == 0 || ArgTys.size() < Record.size() - 2)
|
| - return Error("invalid type in function type");
|
| + return Error(InvalidType, "invalid type in function type");
|
|
|
| ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
|
| break;
|
| }
|
| case naclbitc::TYPE_CODE_VECTOR: { // VECTOR: [numelts, eltty]
|
| if (Record.size() != 2)
|
| - return Error("Invalid VECTOR type record");
|
| + return Error(InvalidRecord, "Invalid VECTOR type record");
|
| if ((ResultTy = getTypeByID(Record[1])))
|
| ResultTy = VectorType::get(ResultTy, Record[0]);
|
| else
|
| - return Error("invalid type in vector type");
|
| + return Error(InvalidType, "invalid type in vector type");
|
| break;
|
| }
|
| }
|
|
|
| if (NumRecords >= TypeList.size())
|
| - return Error("invalid TYPE table");
|
| + return Error(MalformedBlock, "invalid TYPE table");
|
| assert(ResultTy && "Didn't read a type?");
|
| assert(TypeList[NumRecords] == 0 && "Already read type?");
|
| TypeList[NumRecords++] = ResultTy;
|
| }
|
| + return std::error_code();
|
| }
|
|
|
| namespace {
|
| @@ -310,7 +360,7 @@ public:
|
| NumGlobals(0),
|
| StartBit(Stream.GetCurrentBitNo()) {}
|
|
|
| - bool GenerateGlobalVarsPass() {
|
| + std::error_code GenerateGlobalVarsPass() {
|
| InitPass();
|
|
|
| // The type for the initializer of the global variable.
|
| @@ -327,11 +377,13 @@ public:
|
| switch (Entry.Kind) {
|
| case NaClBitstreamEntry::SubBlock:
|
| case NaClBitstreamEntry::Error:
|
| - return Reader.Error("Error in the global vars block");
|
| + return Reader.Error(NaClBitcodeReader::MalformedBlock,
|
| + "Error in the global vars block");
|
| case NaClBitstreamEntry::EndBlock:
|
| if (ProcessingGlobal || NumGlobals != (NextValueNo - FirstValueNo))
|
| - return Reader.Error("Error in the global vars block");
|
| - return false;
|
| + return Reader.Error(NaClBitcodeReader::MalformedBlock,
|
| + "Error in the global vars block");
|
| + return std::error_code();
|
| case NaClBitstreamEntry::Record:
|
| // The interesting case.
|
| break;
|
| @@ -341,11 +393,14 @@ public:
|
| Record.clear();
|
| unsigned Bitcode = Stream.readRecord(Entry.ID, Record);
|
| switch (Bitcode) {
|
| - default: return Reader.Error("Unknown global variable entry");
|
| + default:
|
| + return Reader.Error(NaClBitcodeReader::InvalidValue,
|
| + "Unknown global variable entry");
|
| case naclbitc::GLOBALVAR_VAR:
|
| // Start the definition of a global variable.
|
| if (ProcessingGlobal || Record.size() != 2)
|
| - return Reader.Error("Bad GLOBALVAR_VAR record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Bad GLOBALVAR_VAR record");
|
| ProcessingGlobal = true;
|
| VarAlignment = (1 << Record[0]) >> 1;
|
| VarIsConstant = Record[1] != 0;
|
| @@ -358,13 +413,15 @@ public:
|
| // Record[0].
|
| if (!ProcessingGlobal || !VarType.empty() ||
|
| VarInitializersNeeded != 1 || Record.size() != 1)
|
| - return Reader.Error("Bad GLOBALVAR_COMPOUND record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Bad GLOBALVAR_COMPOUND record");
|
| VarInitializersNeeded = Record[0];
|
| break;
|
| case naclbitc::GLOBALVAR_ZEROFILL: {
|
| // Define a type that defines a sequence of zero-filled bytes.
|
| if (!ProcessingGlobal || Record.size() != 1)
|
| - return Reader.Error("Bad GLOBALVAR_ZEROFILL record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Bad GLOBALVAR_ZEROFILL record");
|
| VarType.push_back(ArrayType::get(
|
| Type::getInt8Ty(Context), Record[0]));
|
| break;
|
| @@ -372,7 +429,8 @@ public:
|
| case naclbitc::GLOBALVAR_DATA: {
|
| // Defines a type defined by a sequence of byte values.
|
| if (!ProcessingGlobal || Record.size() < 1)
|
| - return Reader.Error("Bad GLOBALVAR_DATA record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Bad GLOBALVAR_DATA record");
|
| VarType.push_back(ArrayType::get(
|
| Type::getInt8Ty(Context), Record.size()));
|
| break;
|
| @@ -380,13 +438,15 @@ public:
|
| case naclbitc::GLOBALVAR_RELOC: {
|
| // Define a relocation initializer type.
|
| if (!ProcessingGlobal || Record.size() < 1 || Record.size() > 2)
|
| - return Reader.Error("Bad GLOBALVAR_RELOC record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Bad GLOBALVAR_RELOC record");
|
| VarType.push_back(IntegerType::get(Context, 32));
|
| break;
|
| }
|
| case naclbitc::GLOBALVAR_COUNT:
|
| if (Record.size() != 1 || NumGlobals != 0)
|
| - return Reader.Error("Invalid global count record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Invalid global count record");
|
| NumGlobals = Record[0];
|
| break;
|
| }
|
| @@ -399,6 +459,7 @@ public:
|
| switch (VarType.size()) {
|
| case 0:
|
| return Reader.Error(
|
| + NaClBitcodeReader::InvalidRecord,
|
| "No initializer for global variable in global vars block");
|
| case 1:
|
| Ty = VarType[0];
|
| @@ -419,9 +480,10 @@ public:
|
| VarInitializersNeeded = 0;
|
| VarType.clear();
|
| }
|
| + return std::error_code();
|
| }
|
|
|
| - bool GenerateGlobalVarInitsPass() {
|
| + std::error_code GenerateGlobalVarInitsPass() {
|
| InitPass();
|
| // The initializer for the global variable.
|
| SmallVector<Constant *, 10> VarInit;
|
| @@ -432,11 +494,13 @@ public:
|
| switch (Entry.Kind) {
|
| case NaClBitstreamEntry::SubBlock:
|
| case NaClBitstreamEntry::Error:
|
| - return Reader.Error("Error in the global vars block");
|
| + return Reader.Error(NaClBitcodeReader::MalformedBlock,
|
| + "Error in the global vars block");
|
| case NaClBitstreamEntry::EndBlock:
|
| if (ProcessingGlobal || NumGlobals != (NextValueNo - FirstValueNo))
|
| - return Reader.Error("Error in the global vars block");
|
| - return false;
|
| + return Reader.Error(NaClBitcodeReader::MalformedBlock,
|
| + "Error in the global vars block");
|
| + return std::error_code();
|
| case NaClBitstreamEntry::Record:
|
| if (Entry.ID == naclbitc::DEFINE_ABBREV) {
|
| Stream.SkipAbbrevRecord();
|
| @@ -445,14 +509,17 @@ public:
|
| // The interesting case.
|
| break;
|
| default:
|
| - return Reader.Error("Unexpected record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Unexpected record");
|
| }
|
|
|
| // Read a record.
|
| Record.clear();
|
| unsigned Bitcode = Stream.readRecord(Entry.ID, Record);
|
| switch (Bitcode) {
|
| - default: return Reader.Error("Unknown global variable entry 2");
|
| + default:
|
| + return Reader.Error(NaClBitcodeReader::InvalidValue,
|
| + "Unknown global variable entry 2");
|
| case naclbitc::GLOBALVAR_VAR:
|
| // Start the definition of a global variable.
|
| ProcessingGlobal = true;
|
| @@ -465,13 +532,15 @@ public:
|
| // Record[0].
|
| if (!ProcessingGlobal || !VarInit.empty() ||
|
| VarInitializersNeeded != 1 || Record.size() != 1)
|
| - return Reader.Error("Bad GLOBALVAR_COMPOUND record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Bad GLOBALVAR_COMPOUND record");
|
| VarInitializersNeeded = Record[0];
|
| break;
|
| case naclbitc::GLOBALVAR_ZEROFILL: {
|
| // Define an initializer that defines a sequence of zero-filled bytes.
|
| if (!ProcessingGlobal || Record.size() != 1)
|
| - return Reader.Error("Bad GLOBALVAR_ZEROFILL record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Bad GLOBALVAR_ZEROFILL record");
|
| Type *Ty = ArrayType::get(Type::getInt8Ty(Context),
|
| Record[0]);
|
| Constant *Zero = ConstantAggregateZero::get(Ty);
|
| @@ -481,7 +550,8 @@ public:
|
| case naclbitc::GLOBALVAR_DATA: {
|
| // Defines an initializer defined by a sequence of byte values.
|
| if (!ProcessingGlobal || Record.size() < 1)
|
| - return Reader.Error("Bad GLOBALVAR_DATA record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Bad GLOBALVAR_DATA record");
|
| unsigned Size = Record.size();
|
| uint8_t *Buf = new uint8_t[Size];
|
| assert(Buf);
|
| @@ -496,7 +566,8 @@ public:
|
| case naclbitc::GLOBALVAR_RELOC: {
|
| // Define a relocation initializer.
|
| if (!ProcessingGlobal || Record.size() < 1 || Record.size() > 2)
|
| - return Reader.Error("Bad GLOBALVAR_RELOC record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Bad GLOBALVAR_RELOC record");
|
| Constant *BaseVal = cast<Constant>(ValueList[Record[0]]);
|
| Type *IntPtrType = IntegerType::get(Context, 32);
|
| Constant *Val = ConstantExpr::getPtrToInt(BaseVal, IntPtrType);
|
| @@ -510,7 +581,8 @@ public:
|
| }
|
| case naclbitc::GLOBALVAR_COUNT:
|
| if (Record.size() != 1)
|
| - return Reader.Error("Invalid global count record");
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| + "Invalid global count record");
|
| // Note: NumGlobals should have been set in GenerateGlobalVarsPass.
|
| // Fail if methods are called in wrong order.
|
| assert(NumGlobals == Record[0]);
|
| @@ -524,7 +596,7 @@ public:
|
| Constant *Init = 0;
|
| switch (VarInit.size()) {
|
| case 0:
|
| - return Reader.Error(
|
| + return Reader.Error(NaClBitcodeReader::InvalidRecord,
|
| "No initializer for global variable in global vars block");
|
| case 1:
|
| Init = VarInit[0];
|
| @@ -539,24 +611,26 @@ public:
|
| VarInitializersNeeded = 0;
|
| VarInit.clear();
|
| }
|
| + return std::error_code();
|
| }
|
| };
|
|
|
| } // End anonymous namespace.
|
|
|
| -bool NaClBitcodeReader::ParseGlobalVars() {
|
| +std::error_code NaClBitcodeReader::ParseGlobalVars() {
|
| if (Stream.EnterSubBlock(naclbitc::GLOBALVAR_BLOCK_ID))
|
| - return Error("Malformed block record");
|
| + return Error(InvalidRecord, "Malformed block record");
|
|
|
| ParseGlobalsHandler PassHandler(*this, ValueList, Stream, Context, TheModule);
|
| - if (PassHandler.GenerateGlobalVarsPass()) return true;
|
| + if (std::error_code EC = PassHandler.GenerateGlobalVarsPass())
|
| + return EC;
|
| return PassHandler.GenerateGlobalVarInitsPass();
|
| }
|
|
|
| -bool NaClBitcodeReader::ParseValueSymbolTable() {
|
| +std::error_code NaClBitcodeReader::ParseValueSymbolTable() {
|
| DEBUG(dbgs() << "-> ParseValueSymbolTable\n");
|
| if (Stream.EnterSubBlock(naclbitc::VALUE_SYMTAB_BLOCK_ID))
|
| - return Error("Malformed block record");
|
| + return Error(InvalidRecord, "Malformed block record");
|
|
|
| SmallVector<uint64_t, 64> Record;
|
|
|
| @@ -568,10 +642,10 @@ bool NaClBitcodeReader::ParseValueSymbolTable() {
|
| switch (Entry.Kind) {
|
| case NaClBitstreamEntry::SubBlock: // Handled for us already.
|
| case NaClBitstreamEntry::Error:
|
| - return Error("malformed value symbol table block");
|
| + return Error(MalformedBlock, "malformed value symbol table block");
|
| case NaClBitstreamEntry::EndBlock:
|
| DEBUG(dbgs() << "<- ParseValueSymbolTable\n");
|
| - return false;
|
| + return std::error_code();
|
| case NaClBitstreamEntry::Record:
|
| // The interesting case.
|
| break;
|
| @@ -584,10 +658,10 @@ bool NaClBitcodeReader::ParseValueSymbolTable() {
|
| break;
|
| case naclbitc::VST_CODE_ENTRY: { // VST_ENTRY: [valueid, namechar x N]
|
| if (ConvertToString(Record, 1, ValueName))
|
| - return Error("Invalid VST_ENTRY record");
|
| + return Error(InvalidRecord, "Invalid VST_ENTRY record");
|
| unsigned ValueID = Record[0];
|
| if (ValueID >= ValueList.size())
|
| - return Error("Invalid Value ID in VST_ENTRY record");
|
| + return Error(InvalidValue, "Invalid Value ID in VST_ENTRY record");
|
| Value *V = ValueList[ValueID];
|
|
|
| V->setName(StringRef(ValueName.data(), ValueName.size()));
|
| @@ -596,10 +670,10 @@ bool NaClBitcodeReader::ParseValueSymbolTable() {
|
| }
|
| case naclbitc::VST_CODE_BBENTRY: {
|
| if (ConvertToString(Record, 1, ValueName))
|
| - return Error("Invalid VST_BBENTRY record");
|
| + return Error(InvalidRecord, "Invalid VST_BBENTRY record");
|
| BasicBlock *BB = getBasicBlock(Record[0]);
|
| if (BB == 0)
|
| - return Error("Invalid BB ID in VST_BBENTRY record");
|
| + return Error(InvalidValue, "Invalid BB ID in VST_BBENTRY record");
|
|
|
| BB->setName(StringRef(ValueName.data(), ValueName.size()));
|
| ValueName.clear();
|
| @@ -609,10 +683,10 @@ bool NaClBitcodeReader::ParseValueSymbolTable() {
|
| }
|
| }
|
|
|
| -bool NaClBitcodeReader::ParseConstants() {
|
| +std::error_code NaClBitcodeReader::ParseConstants() {
|
| DEBUG(dbgs() << "-> ParseConstants\n");
|
| if (Stream.EnterSubBlock(naclbitc::CONSTANTS_BLOCK_ID))
|
| - return Error("Malformed block record");
|
| + return Error(InvalidRecord, "Malformed block record");
|
|
|
| SmallVector<uint64_t, 64> Record;
|
|
|
| @@ -625,12 +699,13 @@ bool NaClBitcodeReader::ParseConstants() {
|
| switch (Entry.Kind) {
|
| case NaClBitstreamEntry::SubBlock: // Handled for us already.
|
| case NaClBitstreamEntry::Error:
|
| - return Error("malformed block record in AST file");
|
| + return Error(MalformedBlock, "malformed block record in AST file");
|
| case NaClBitstreamEntry::EndBlock:
|
| if (NextCstNo != ValueList.size())
|
| - return Error("Invalid constant reference!");
|
| + return Error(InvalidConstantReference,
|
| + "Invalid constant reference!");
|
| DEBUG(dbgs() << "<- ParseConstants\n");
|
| - return false;
|
| + return std::error_code();
|
| case NaClBitstreamEntry::Record:
|
| // The interesting case.
|
| break;
|
| @@ -646,26 +721,28 @@ bool NaClBitcodeReader::ParseConstants() {
|
| raw_string_ostream StrM(Message);
|
| StrM << "Invalid Constant code: " << BitCode;
|
| StrM.flush();
|
| - return Error(Message);
|
| + return Error(InvalidValue, Message);
|
| }
|
| case naclbitc::CST_CODE_UNDEF: // UNDEF
|
| V = UndefValue::get(CurTy);
|
| break;
|
| case naclbitc::CST_CODE_SETTYPE: // SETTYPE: [typeid]
|
| if (Record.empty())
|
| - return Error("Malformed CST_SETTYPE record");
|
| + return Error(NaClBitcodeReader::InvalidRecord,
|
| + "Malformed CST_SETTYPE record");
|
| if (Record[0] >= TypeList.size())
|
| - return Error("Invalid Type ID in CST_SETTYPE record");
|
| + return Error(NaClBitcodeReader::InvalidType,
|
| + "Invalid Type ID in CST_SETTYPE record");
|
| CurTy = TypeList[Record[0]];
|
| continue; // Skip the ValueList manipulation.
|
| case naclbitc::CST_CODE_INTEGER: // INTEGER: [intval]
|
| if (!CurTy->isIntegerTy() || Record.empty())
|
| - return Error("Invalid CST_INTEGER record");
|
| + return Error(InvalidRecord, "Invalid CST_INTEGER record");
|
| V = ConstantInt::get(CurTy, NaClDecodeSignRotatedValue(Record[0]));
|
| break;
|
| case naclbitc::CST_CODE_FLOAT: { // FLOAT: [fpval]
|
| if (Record.empty())
|
| - return Error("Invalid FLOAT record");
|
| + return Error(NaClBitcodeReader::InvalidRecord, "Invalid FLOAT record");
|
| if (CurTy->isFloatTy())
|
| V = ConstantFP::get(Context, APFloat(APFloat::IEEEsingle,
|
| APInt(32, (uint32_t)Record[0])));
|
| @@ -673,7 +750,8 @@ bool NaClBitcodeReader::ParseConstants() {
|
| V = ConstantFP::get(Context, APFloat(APFloat::IEEEdouble,
|
| APInt(64, Record[0])));
|
| else
|
| - return Error("Unknown type for FLOAT record");
|
| + return Error(NaClBitcodeReader::InvalidRecord,
|
| + "Unknown type for FLOAT record");
|
| break;
|
| }
|
| }
|
| @@ -681,16 +759,18 @@ bool NaClBitcodeReader::ParseConstants() {
|
| ValueList.AssignValue(V, NextCstNo);
|
| ++NextCstNo;
|
| }
|
| + return std::error_code();
|
| }
|
|
|
| /// RememberAndSkipFunctionBody - When we see the block for a function body,
|
| /// remember where it is and then skip it. This lets us lazily deserialize the
|
| /// functions.
|
| -bool NaClBitcodeReader::RememberAndSkipFunctionBody() {
|
| +std::error_code NaClBitcodeReader::RememberAndSkipFunctionBody() {
|
| DEBUG(dbgs() << "-> RememberAndSkipFunctionBody\n");
|
| // Get the function we are talking about.
|
| if (FunctionsWithBodies.empty())
|
| - return Error("Insufficient function protos");
|
| + return Error(InsufficientFunctionProtos,
|
| + "Insufficient function protos");
|
|
|
| Function *Fn = FunctionsWithBodies.back();
|
| FunctionsWithBodies.pop_back();
|
| @@ -701,12 +781,12 @@ bool NaClBitcodeReader::RememberAndSkipFunctionBody() {
|
|
|
| // Skip over the function block for now.
|
| if (Stream.SkipBlock())
|
| - return Error("Malformed block record");
|
| + return Error(InvalidSkippedBlock, "Unable to skip function block.");
|
| DEBUG(dbgs() << "<- RememberAndSkipFunctionBody\n");
|
| - return false;
|
| + return std::error_code();
|
| }
|
|
|
| -bool NaClBitcodeReader::GlobalCleanup() {
|
| +std::error_code NaClBitcodeReader::GlobalCleanup() {
|
| // Look for intrinsic functions which need to be upgraded at some point
|
| for (Module::iterator FI = TheModule->begin(), FE = TheModule->end();
|
| FI != FE; ++FI) {
|
| @@ -720,7 +800,7 @@ bool NaClBitcodeReader::GlobalCleanup() {
|
| GI = TheModule->global_begin(), GE = TheModule->global_end();
|
| GI != GE; ++GI)
|
| UpgradeGlobalVariable(GI);
|
| - return false;
|
| + return std::error_code();
|
| }
|
|
|
| FunctionType *NaClBitcodeReader::AddPointerTypesToIntrinsicType(
|
| @@ -777,12 +857,12 @@ void NaClBitcodeReader::AddPointerTypesToIntrinsicParams() {
|
| }
|
| }
|
|
|
| -bool NaClBitcodeReader::ParseModule(bool Resume) {
|
| +std::error_code NaClBitcodeReader::ParseModule(bool Resume) {
|
| DEBUG(dbgs() << "-> ParseModule\n");
|
| if (Resume)
|
| Stream.JumpToBit(NextUnreadBit);
|
| else if (Stream.EnterSubBlock(naclbitc::MODULE_BLOCK_ID))
|
| - return Error("Malformed block record");
|
| + return Error(InvalidRecord, "Malformed block record");
|
|
|
| SmallVector<uint64_t, 64> Record;
|
|
|
| @@ -792,8 +872,7 @@ bool NaClBitcodeReader::ParseModule(bool Resume) {
|
|
|
| switch (Entry.Kind) {
|
| case NaClBitstreamEntry::Error:
|
| - Error("malformed module block");
|
| - return true;
|
| + return Error(MalformedBlock, "malformed module block");
|
| case NaClBitstreamEntry::EndBlock:
|
| DEBUG(dbgs() << "<- ParseModule\n");
|
| return GlobalCleanup();
|
| @@ -804,23 +883,23 @@ bool NaClBitcodeReader::ParseModule(bool Resume) {
|
| std::string Message;
|
| raw_string_ostream StrM(Message);
|
| StrM << "Unknown block ID: " << Entry.ID;
|
| - return Error(StrM.str());
|
| + return Error(InvalidRecord, StrM.str());
|
| }
|
| case naclbitc::BLOCKINFO_BLOCK_ID:
|
| if (Stream.ReadBlockInfoBlock(0))
|
| - return Error("Malformed BlockInfoBlock");
|
| + return Error(MalformedBlock, "Malformed BlockInfoBlock");
|
| break;
|
| case naclbitc::TYPE_BLOCK_ID_NEW:
|
| - if (ParseTypeTable())
|
| - return true;
|
| + if (std::error_code EC = ParseTypeTable())
|
| + return EC;
|
| break;
|
| case naclbitc::GLOBALVAR_BLOCK_ID:
|
| - if (ParseGlobalVars())
|
| - return true;
|
| + if (std::error_code EC = ParseGlobalVars())
|
| + return EC;
|
| break;
|
| case naclbitc::VALUE_SYMTAB_BLOCK_ID:
|
| - if (ParseValueSymbolTable())
|
| - return true;
|
| + if (std::error_code EC = ParseValueSymbolTable())
|
| + return EC;
|
| SeenValueSymbolTable = true;
|
| // Now that we know the names of the intrinsics, we can add
|
| // pointer types to the intrinsic declarations' types.
|
| @@ -831,13 +910,13 @@ bool NaClBitcodeReader::ParseModule(bool Resume) {
|
| // FunctionsWithBodies list.
|
| if (!SeenFirstFunctionBody) {
|
| std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end());
|
| - if (GlobalCleanup())
|
| - return true;
|
| + if (std::error_code EC = GlobalCleanup())
|
| + return EC;
|
| SeenFirstFunctionBody = true;
|
| }
|
|
|
| - if (RememberAndSkipFunctionBody())
|
| - return true;
|
| + if (std::error_code EC = RememberAndSkipFunctionBody())
|
| + return EC;
|
|
|
| // For streaming bitcode, suspend parsing when we reach the function
|
| // bodies. Subsequent materialization calls will resume it when
|
| @@ -848,7 +927,7 @@ bool NaClBitcodeReader::ParseModule(bool Resume) {
|
| if (LazyStreamer && SeenValueSymbolTable) {
|
| NextUnreadBit = Stream.GetCurrentBitNo();
|
| DEBUG(dbgs() << "<- ParseModule\n");
|
| - return false;
|
| + return std::error_code();
|
| }
|
| break;
|
| }
|
| @@ -867,38 +946,41 @@ bool NaClBitcodeReader::ParseModule(bool Resume) {
|
| raw_string_ostream StrM(Message);
|
| StrM << "Invalid MODULE_CODE: " << Selector;
|
| StrM.flush();
|
| - return Error(Message);
|
| + return Error(InvalidValue, Message);
|
| }
|
| case naclbitc::MODULE_CODE_VERSION: { // VERSION: [version#]
|
| if (Record.size() < 1)
|
| - return Error("Malformed MODULE_CODE_VERSION");
|
| + return Error(InvalidRecord, "Malformed MODULE_CODE_VERSION");
|
| // Only version #1 is supported for PNaCl. Version #0 is not supported.
|
| unsigned module_version = Record[0];
|
| if (module_version != 1)
|
| - return Error("Unknown bitstream version!");
|
| + return Error(InvalidValue, "Unknown bitstream version!");
|
| break;
|
| }
|
| // FUNCTION: [type, callingconv, isproto, linkage]
|
| case naclbitc::MODULE_CODE_FUNCTION: {
|
| if (Record.size() < 4)
|
| - return Error("Invalid MODULE_CODE_FUNCTION record");
|
| + return Error(InvalidRecord, "Invalid MODULE_CODE_FUNCTION record");
|
| Type *Ty = getTypeByID(Record[0]);
|
| - if (!Ty) return Error("Invalid MODULE_CODE_FUNCTION record");
|
| + if (!Ty)
|
| + return Error(InvalidType, "Invalid MODULE_CODE_FUNCTION record");
|
| FunctionType *FTy = dyn_cast<FunctionType>(Ty);
|
| if (!FTy)
|
| - return Error("Function not declared with a function type!");
|
| + return Error(InvalidType,
|
| + "Function not declared with a function type!");
|
|
|
| Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage,
|
| "", TheModule);
|
|
|
| CallingConv::ID CallingConv;
|
| if (!naclbitc::DecodeCallingConv(Record[1], CallingConv))
|
| - return Error("PNaCl bitcode contains invalid calling conventions.");
|
| + return Error(InvalidValue,
|
| + "PNaCl bitcode contains invalid calling conventions.");
|
| Func->setCallingConv(CallingConv);
|
| bool isProto = Record[2];
|
| GlobalValue::LinkageTypes Linkage;
|
| if (!naclbitc::DecodeLinkage(Record[3], Linkage))
|
| - return Error("Unknown linkage type");
|
| + return Error(InvalidValue, "Unknown linkage type");
|
| Func->setLinkage(Linkage);
|
| ValueList.push_back(Func);
|
|
|
| @@ -913,13 +995,14 @@ bool NaClBitcodeReader::ParseModule(bool Resume) {
|
| }
|
| Record.clear();
|
| }
|
| + return std::error_code();
|
| }
|
|
|
| const char *llvm::PNaClDataLayout =
|
| "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"
|
| "f32:32:32-f64:64:64-p:32:32:32-v128:32:32";
|
|
|
| -bool NaClBitcodeReader::ParseBitcodeInto(Module *M) {
|
| +std::error_code NaClBitcodeReader::ParseBitcodeInto(Module *M) {
|
| TheModule = 0;
|
|
|
| // PNaCl does not support different DataLayouts in pexes, so we
|
| @@ -931,63 +1014,67 @@ bool NaClBitcodeReader::ParseBitcodeInto(Module *M) {
|
| // correct DataLayout if it is run on a pexe.
|
| M->setDataLayout(PNaClDataLayout);
|
|
|
| - if (InitStream()) return true; // InitSream will set the error string.
|
| + if (std::error_code EC = InitStream())
|
| + return EC;
|
|
|
| // We expect a number of well-defined blocks, though we don't necessarily
|
| // need to understand them all.
|
| while (1) {
|
| if (Stream.AtEndOfStream())
|
| - return false;
|
| + return std::error_code();
|
|
|
| NaClBitstreamEntry Entry =
|
| Stream.advance(NaClBitstreamCursor::AF_DontAutoprocessAbbrevs, 0);
|
|
|
| switch (Entry.Kind) {
|
| case NaClBitstreamEntry::Error:
|
| - Error("malformed module file");
|
| - return true;
|
| + return Error(MalformedBlock, "malformed module file");
|
| case NaClBitstreamEntry::EndBlock:
|
| - return false;
|
| + return std::error_code();
|
|
|
| case NaClBitstreamEntry::SubBlock:
|
| switch (Entry.ID) {
|
| case naclbitc::BLOCKINFO_BLOCK_ID:
|
| if (Stream.ReadBlockInfoBlock(0))
|
| - return Error("Malformed BlockInfoBlock");
|
| + return Error(MalformedBlock, "Malformed BlockInfoBlock");
|
| break;
|
| case naclbitc::MODULE_BLOCK_ID:
|
| // Reject multiple MODULE_BLOCK's in a single bitstream.
|
| if (TheModule)
|
| - return Error("Multiple MODULE_BLOCKs in same stream");
|
| + return Error(InvalidMultipleBlocks,
|
| + "Multiple MODULE_BLOCKs in same stream");
|
| TheModule = M;
|
| - if (ParseModule(false))
|
| - return true;
|
| - if (LazyStreamer) return false;
|
| + if (std::error_code EC = ParseModule(false))
|
| + return EC;
|
| + if (LazyStreamer)
|
| + return std::error_code();
|
| break;
|
| default:
|
| if (Stream.SkipBlock())
|
| - return Error("Malformed block record");
|
| + return Error(InvalidSkippedBlock,
|
| + "Unable to skip unknown top-level block");
|
| break;
|
| }
|
| continue;
|
| case NaClBitstreamEntry::Record:
|
| // There should be no records in the top-level of blocks.
|
| - return Error("Invalid record at top-level");
|
| + return Error(InvalidRecord, "Invalid record at top-level");
|
| }
|
| }
|
| }
|
|
|
| // Returns true if error occured installing I into BB.
|
| -bool NaClBitcodeReader::InstallInstruction(
|
| +std::error_code NaClBitcodeReader::InstallInstruction(
|
| BasicBlock *BB, Instruction *I) {
|
| // Add instruction to end of current BB. If there is no current BB, reject
|
| // this file.
|
| if (BB == 0) {
|
| delete I;
|
| - return Error("Invalid instruction with no BB");
|
| + return Error(InvalidInstructionWithNoBB,
|
| + "Instruction with no BB, can't install");
|
| }
|
| BB->getInstList().push_back(I);
|
| - return false;
|
| + return std::error_code();
|
| }
|
|
|
| CastInst *
|
| @@ -1042,10 +1129,10 @@ Value *NaClBitcodeReader::ConvertOpToType(Value *Op, Type *T,
|
| }
|
|
|
| /// ParseFunctionBody - Lazily parse the specified function body block.
|
| -bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| +std::error_code NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| DEBUG(dbgs() << "-> ParseFunctionBody\n");
|
| if (Stream.EnterSubBlock(naclbitc::FUNCTION_BLOCK_ID))
|
| - return Error("Malformed block record");
|
| + return Error(InvalidRecord, "Malformed block record");
|
|
|
| unsigned ModuleValueListSize = ValueList.size();
|
|
|
| @@ -1064,28 +1151,28 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
|
|
| switch (Entry.Kind) {
|
| case NaClBitstreamEntry::Error:
|
| - return Error("Bitcode error in function block");
|
| + return Error(MalformedBlock, "Bitcode error in function block");
|
| case NaClBitstreamEntry::EndBlock:
|
| goto OutOfRecordLoop;
|
|
|
| case NaClBitstreamEntry::SubBlock:
|
| switch (Entry.ID) {
|
| default: // Skip unknown content.
|
| - dbgs() << "default skip block\n";
|
| if (Stream.SkipBlock())
|
| - return Error("Malformed block record");
|
| + return Error(InvalidSkippedBlock,
|
| + "Unable to skip unknown block in function block");
|
| break;
|
| case naclbitc::CONSTANTS_BLOCK_ID:
|
| - if (ParseConstants())
|
| - return true;
|
| + if (std::error_code EC = ParseConstants())
|
| + return EC;
|
| NextValueNo = ValueList.size();
|
| break;
|
| case naclbitc::VALUE_SYMTAB_BLOCK_ID:
|
| if (PNaClAllowLocalSymbolTables) {
|
| - if (ParseValueSymbolTable())
|
| - return true;
|
| + if (std::error_code EC = ParseValueSymbolTable())
|
| + return EC;
|
| } else {
|
| - return Error("Local value symbol tables not allowed");
|
| + return Error(InvalidRecord, "Local value symbol tables not allowed");
|
| }
|
| break;
|
| }
|
| @@ -1109,12 +1196,12 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| StrM << " " << Record[I];
|
| }
|
| StrM << ">";
|
| - return Error(StrM.str());
|
| + return Error(InvalidRecord, StrM.str());
|
| }
|
|
|
| case naclbitc::FUNC_CODE_DECLAREBLOCKS: // DECLAREBLOCKS: [nblocks]
|
| if (Record.size() != 1 || Record[0] == 0)
|
| - return Error("Invalid DECLAREBLOCKS record");
|
| + return Error(InvalidRecord, "Invalid DECLAREBLOCKS record");
|
| // Create all the basic blocks for the function.
|
| FunctionBBs.resize(Record[0]);
|
| for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i) {
|
| @@ -1133,14 +1220,14 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| if (popValue(Record, &OpNum, NextValueNo, &LHS) ||
|
| popValue(Record, &OpNum, NextValueNo, &RHS) ||
|
| OpNum+1 > Record.size())
|
| - return Error("Invalid BINOP record");
|
| + return Error(InvalidRecord, "Invalid BINOP record");
|
|
|
| LHS = ConvertOpToScalar(LHS, CurBBNo);
|
| RHS = ConvertOpToScalar(RHS, CurBBNo);
|
|
|
| Instruction::BinaryOps Opc;
|
| if (!naclbitc::DecodeBinaryOpcode(Record[OpNum++], LHS->getType(), Opc))
|
| - return Error("Invalid binary opcode in BINOP record");
|
| + return Error(InvalidValue, "Invalid binary opcode in BINOP record");
|
| I = BinaryOperator::Create(Opc, LHS, RHS);
|
| break;
|
| }
|
| @@ -1149,14 +1236,14 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| Value *Op;
|
| if (popValue(Record, &OpNum, NextValueNo, &Op) ||
|
| OpNum+2 != Record.size())
|
| - return Error("Invalid CAST record: bad record size");
|
| + return Error(InvalidRecord, "Invalid CAST record: bad record size");
|
|
|
| Type *ResTy = getTypeByID(Record[OpNum]);
|
| if (ResTy == 0)
|
| - return Error("Invalid CAST record: bad type ID");
|
| + return Error(InvalidType, "Invalid CAST record: bad type ID");
|
| Instruction::CastOps Opc;
|
| if (!naclbitc::DecodeCastOpcode(Record[OpNum+1], Opc)) {
|
| - return Error("Invalid CAST record: bad opcode");
|
| + return Error(InvalidValue, "Invalid CAST record: bad opcode");
|
| }
|
|
|
| // If a ptrtoint cast was elided on the argument of the cast,
|
| @@ -1187,7 +1274,7 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| popValue(Record, &OpNum, NextValueNo, &FalseVal) ||
|
| popValue(Record, &OpNum, NextValueNo, &Cond) ||
|
| OpNum != Record.size())
|
| - return Error("Invalid SELECT record");
|
| + return Error(InvalidRecord, "Invalid SELECT record");
|
|
|
| TrueVal = ConvertOpToScalar(TrueVal, CurBBNo);
|
| FalseVal = ConvertOpToScalar(FalseVal, CurBBNo);
|
| @@ -1197,11 +1284,12 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| dyn_cast<VectorType>(Cond->getType())) {
|
| // expect <n x i1>
|
| if (vector_type->getElementType() != Type::getInt1Ty(Context))
|
| - return Error("Invalid SELECT vector condition type");
|
| + return Error(InvalidTypeForValue,
|
| + "Invalid SELECT vector condition type");
|
| } else {
|
| // expect i1
|
| if (Cond->getType() != Type::getInt1Ty(Context))
|
| - return Error("Invalid SELECT condition type");
|
| + return Error(InvalidTypeForValue, "Invalid SELECT condition type");
|
| }
|
|
|
| I = SelectInst::Create(Cond, TrueVal, FalseVal);
|
| @@ -1213,11 +1301,11 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| Value *Vec, *Idx;
|
| if (popValue(Record, &OpNum, NextValueNo, &Vec) ||
|
| popValue(Record, &OpNum, NextValueNo, &Idx) || OpNum != Record.size())
|
| - return Error("Invalid EXTRACTELEMENT record");
|
| + return Error(InvalidRecord, "Invalid EXTRACTELEMENT record");
|
|
|
| // expect i32
|
| if (Idx->getType() != Type::getInt32Ty(Context))
|
| - return Error("Invalid EXTRACTELEMENT index type");
|
| + return Error(InvalidTypeForValue, "Invalid EXTRACTELEMENT index type");
|
|
|
| I = ExtractElementInst::Create(Vec, Idx);
|
| break;
|
| @@ -1229,17 +1317,18 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| if (popValue(Record, &OpNum, NextValueNo, &Vec) ||
|
| popValue(Record, &OpNum, NextValueNo, &Elt) ||
|
| popValue(Record, &OpNum, NextValueNo, &Idx) || OpNum != Record.size())
|
| - return Error("Invalid INSERTELEMENT record");
|
| + return Error(InvalidRecord, "Invalid INSERTELEMENT record");
|
|
|
| // expect vector type
|
| if (!isa<VectorType>(Vec->getType()))
|
| - return Error("Invalid INSERTELEMENT vector type");
|
| + return Error(InvalidTypeForValue, "Invalid INSERTELEMENT vector type");
|
| // match vector and element types
|
| if (cast<VectorType>(Vec->getType())->getElementType() != Elt->getType())
|
| - return Error("Mismatched INSERTELEMENT vector and element type");
|
| + return Error(InvalidTypeForValue,
|
| + "Mismatched INSERTELEMENT vector and element type");
|
| // expect i32
|
| if (Idx->getType() != Type::getInt32Ty(Context))
|
| - return Error("Invalid INSERTELEMENT index type");
|
| + return Error(InvalidTypeForValue, "Invalid INSERTELEMENT index type");
|
|
|
| I = InsertElementInst::Create(Vec, Elt, Idx);
|
| break;
|
| @@ -1253,7 +1342,7 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| if (popValue(Record, &OpNum, NextValueNo, &LHS) ||
|
| popValue(Record, &OpNum, NextValueNo, &RHS) ||
|
| OpNum+1 != Record.size())
|
| - return Error("Invalid CMP record");
|
| + return Error(InvalidRecord, "Invalid CMP record");
|
|
|
| LHS = ConvertOpToScalar(LHS, CurBBNo);
|
| RHS = ConvertOpToScalar(RHS, CurBBNo);
|
| @@ -1262,11 +1351,13 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| if (LHS->getType()->isFPOrFPVectorTy()) {
|
| if (!naclbitc::DecodeFcmpPredicate(Record[OpNum], Predicate))
|
| return Error(
|
| + InvalidValue,
|
| "PNaCl bitcode contains invalid floating comparison predicate");
|
| I = new FCmpInst(Predicate, LHS, RHS);
|
| } else {
|
| if (!naclbitc::DecodeIcmpPredicate(Record[OpNum], Predicate))
|
| return Error(
|
| + InvalidValue,
|
| "PNaCl bitcode contains invalid integer comparison predicate");
|
| I = new ICmpInst(Predicate, LHS, RHS);
|
| }
|
| @@ -1284,19 +1375,19 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| unsigned OpNum = 0;
|
| Value *Op = NULL;
|
| if (popValue(Record, &OpNum, NextValueNo, &Op))
|
| - return Error("Invalid RET record");
|
| + return Error(InvalidRecord, "Invalid RET record");
|
| if (OpNum != Record.size())
|
| - return Error("Invalid RET record");
|
| + return Error(InvalidRecord, "Invalid RET record");
|
|
|
| I = ReturnInst::Create(Context, ConvertOpToScalar(Op, CurBBNo));
|
| break;
|
| }
|
| case naclbitc::FUNC_CODE_INST_BR: { // BR: [bb#, bb#, opval] or [bb#]
|
| if (Record.size() != 1 && Record.size() != 3)
|
| - return Error("Invalid BR record");
|
| + return Error(InvalidRecord, "Invalid BR record");
|
| BasicBlock *TrueDest = getBasicBlock(Record[0]);
|
| if (TrueDest == 0)
|
| - return Error("Invalid BR record");
|
| + return Error(InvalidRecord, "Invalid BR record");
|
|
|
| if (Record.size() == 1) {
|
| I = BranchInst::Create(TrueDest);
|
| @@ -1305,23 +1396,24 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| BasicBlock *FalseDest = getBasicBlock(Record[1]);
|
| Value *Cond = getValue(Record, 2, NextValueNo);
|
| if (FalseDest == 0 || Cond == 0)
|
| - return Error("Invalid BR record");
|
| + return Error(InvalidValue, "Invalid BR record");
|
| I = BranchInst::Create(TrueDest, FalseDest, Cond);
|
| }
|
| break;
|
| }
|
| case naclbitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
|
| if (Record.size() < 4)
|
| - return Error("Invalid SWITCH record");
|
| + return Error(InvalidRecord, "Invalid SWITCH record");
|
| Type *OpTy = getTypeByID(Record[0]);
|
| unsigned ValueBitWidth = cast<IntegerType>(OpTy)->getBitWidth();
|
| if (ValueBitWidth > 64)
|
| - return Error("Wide integers are not supported in PNaCl bitcode");
|
| + return Error(InvalidValue,
|
| + "Wide integers are not supported in PNaCl bitcode");
|
|
|
| Value *Cond = getValue(Record, 1, NextValueNo);
|
| BasicBlock *Default = getBasicBlock(Record[2]);
|
| if (OpTy == 0 || Cond == 0 || Default == 0)
|
| - return Error("Invalid SWITCH record");
|
| + return Error(InvalidRecord, "Invalid SWITCH record");
|
|
|
| unsigned NumCases = Record[3];
|
|
|
| @@ -1336,7 +1428,8 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| unsigned NumItems = Record[CurIdx++];
|
| bool isSingleNumber = Record[CurIdx++];
|
| if (NumItems != 1 || !isSingleNumber)
|
| - return Error("Case ranges are not supported in PNaCl bitcode");
|
| + return Error(InvalidRecord,
|
| + "Case ranges are not supported in PNaCl bitcode");
|
|
|
| APInt CaseValue(ValueBitWidth,
|
| NaClDecodeSignRotatedValue(Record[CurIdx++]));
|
| @@ -1351,9 +1444,9 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| break;
|
| case naclbitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...]
|
| if (Record.size() < 1 || ((Record.size()-1)&1))
|
| - return Error("Invalid PHI record");
|
| + return Error(InvalidRecord, "Invalid PHI record");
|
| Type *Ty = getTypeByID(Record[0]);
|
| - if (!Ty) return Error("Invalid PHI record");
|
| + if (!Ty) return Error(InvalidType, "Invalid PHI record");
|
|
|
| PHINode *PN = PHINode::Create(Ty, (Record.size()-1)/2);
|
|
|
| @@ -1365,7 +1458,8 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| V = getValueSigned(Record, 1+i, NextValueNo);
|
| unsigned BBIndex = Record[2+i];
|
| BasicBlock *BB = getBasicBlock(BBIndex);
|
| - if (!V || !BB) return Error("Invalid PHI record");
|
| + if (!V || !BB)
|
| + return Error(InvalidValue, "Invalid PHI record");
|
| if (Ty == IntPtrType) {
|
| // Delay installing scalar casts until all instructions of
|
| // the function are rendered. This guarantees that we insert
|
| @@ -1381,11 +1475,11 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
|
|
| case naclbitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [op, align]
|
| if (Record.size() != 2)
|
| - return Error("Invalid ALLOCA record");
|
| + return Error(InvalidRecord, "Invalid ALLOCA record");
|
| Value *Size;
|
| unsigned OpNum = 0;
|
| if (popValue(Record, &OpNum, NextValueNo, &Size))
|
| - return Error("Invalid ALLOCA record");
|
| + return Error(InvalidRecord, "Invalid ALLOCA record");
|
| unsigned Align = Record[1];
|
| I = new AllocaInst(Type::getInt8Ty(Context), Size, (1 << Align) >> 1);
|
| break;
|
| @@ -1396,14 +1490,15 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| Value *Op;
|
| if (popValue(Record, &OpNum, NextValueNo, &Op) ||
|
| Record.size() != 3)
|
| - return Error("Invalid LOAD record");
|
| + return Error(InvalidRecord, "Invalid LOAD record");
|
|
|
| // Add pointer cast to op.
|
| Type *T = getTypeByID(Record[2]);
|
| - if (T == 0)
|
| - return Error("Invalid type for load instruction");
|
| + if (T == nullptr)
|
| + return Error(InvalidType, "Invalid type for load instruction");
|
| Op = ConvertOpToType(Op, T->getPointerTo(), CurBBNo);
|
| - if (Op == 0) return true;
|
| + if (Op == nullptr)
|
| + return Error(InvalidTypeForValue, "Can't convert cast to type");
|
| I = new LoadInst(Op, "", false, (1 << Record[OpNum]) >> 1);
|
| break;
|
| }
|
| @@ -1414,9 +1509,11 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| if (popValue(Record, &OpNum, NextValueNo, &Ptr) ||
|
| popValue(Record, &OpNum, NextValueNo, &Val) ||
|
| OpNum+1 != Record.size())
|
| - return Error("Invalid STORE record");
|
| + return Error(InvalidRecord, "Invalid STORE record");
|
| Val = ConvertOpToScalar(Val, CurBBNo);
|
| Ptr = ConvertOpToType(Ptr, Val->getType()->getPointerTo(), CurBBNo);
|
| + if (Ptr == nullptr)
|
| + return Error(InvalidTypeForValue, "Can't convert cast to type");
|
| I = new StoreInst(Val, Ptr, false, (1 << Record[OpNum]) >> 1);
|
| break;
|
| }
|
| @@ -1427,14 +1524,14 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| if ((Record.size() < 2) ||
|
| (BitCode == naclbitc::FUNC_CODE_INST_CALL_INDIRECT &&
|
| Record.size() < 3))
|
| - return Error("Invalid CALL record");
|
| + return Error(InvalidRecord, "Invalid CALL record");
|
|
|
| unsigned CCInfo = Record[0];
|
|
|
| unsigned OpNum = 1;
|
| Value *Callee;
|
| if (popValue(Record, &OpNum, NextValueNo, &Callee))
|
| - return Error("Invalid CALL record");
|
| + return Error(InvalidRecord, "Invalid CALL record");
|
|
|
| // Build function type for call.
|
| FunctionType *FTy = 0;
|
| @@ -1449,19 +1546,19 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| FTy = dyn_cast<FunctionType>(OpTy->getElementType());
|
| }
|
| if (FTy == 0)
|
| - return Error("Invalid type for CALL record");
|
| + return Error(InvalidType, "Invalid type for CALL record");
|
| }
|
|
|
| unsigned NumParams = Record.size() - OpNum;
|
| if (FTy && NumParams != FTy->getNumParams())
|
| - return Error("Invalid CALL record");
|
| + return Error(InvalidRecord, "Invalid CALL record");
|
|
|
| // Process call arguments.
|
| SmallVector<Value*, 6> Args;
|
| for (unsigned Index = 0; Index < NumParams; ++Index) {
|
| Value *Arg;
|
| if (popValue(Record, &OpNum, NextValueNo, &Arg))
|
| - Error("Invalid argument in CALL record");
|
| + Error(InvalidValue, "Invalid argument in CALL record");
|
| if (FTy) {
|
| // Add a cast, to a pointer type if necessary, in case this
|
| // is an intrinsic call that takes a pointer argument.
|
| @@ -1486,7 +1583,8 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| I = CallInst::Create(Callee, Args);
|
| CallingConv::ID CallingConv;
|
| if (!naclbitc::DecodeCallingConv(CCInfo>>1, CallingConv))
|
| - return Error("PNaCl bitcode contains invalid calling conventions.");
|
| + return Error(InvalidValue,
|
| + "PNaCl bitcode contains invalid calling conventions.");
|
| cast<CallInst>(I)->setCallingConv(CallingConv);
|
| cast<CallInst>(I)->setTailCall(CCInfo & 1);
|
| break;
|
| @@ -1495,12 +1593,12 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
|
| // Build corresponding forward reference.
|
| if (Record.size() != 2 ||
|
| ValueList.createValueFwdRef(Record[0], getTypeByID(Record[1])))
|
| - return Error("Invalid FORWARDTYPEREF record");
|
| + return Error(InvalidRecord, "Invalid FORWARDTYPEREF record");
|
| continue;
|
| }
|
|
|
| - if (InstallInstruction(CurBB, I))
|
| - return true;
|
| + if (std::error_code EC = InstallInstruction(CurBB, I))
|
| + return EC;
|
|
|
| // If this was a terminator instruction, move to the next block.
|
| if (isa<TerminatorInst>(I)) {
|
| @@ -1550,7 +1648,7 @@ OutOfRecordLoop:
|
| delete A;
|
| }
|
| }
|
| - return Error("Never resolved value found in function!");
|
| + return Error(InvalidValue, "Never resolved value found in function!");
|
| }
|
| }
|
|
|
| @@ -1558,20 +1656,23 @@ OutOfRecordLoop:
|
| ValueList.shrinkTo(ModuleValueListSize);
|
| FunctionBBs.clear();
|
| DEBUG(dbgs() << "-> ParseFunctionBody\n");
|
| - return false;
|
| + return std::error_code();
|
| }
|
|
|
| /// FindFunctionInStream - Find the function body in the bitcode stream
|
| -bool NaClBitcodeReader::FindFunctionInStream(Function *F,
|
| - DenseMap<Function*, uint64_t>::iterator DeferredFunctionInfoIterator) {
|
| +std::error_code NaClBitcodeReader::FindFunctionInStream(
|
| + Function *F,
|
| + DenseMap<Function*, uint64_t>::iterator DeferredFunctionInfoIterator) {
|
| while (DeferredFunctionInfoIterator->second == 0) {
|
| if (Stream.AtEndOfStream())
|
| - return Error("Could not find Function in stream");
|
| + return Error(CouldNotFindFunctionInStream,
|
| + "Could not find Function in stream");
|
| // ParseModule will parse the next body in the stream and set its
|
| // position in the DeferredFunctionInfo map.
|
| - if (ParseModule(true)) return true;
|
| + if (std::error_code EC = ParseModule(true))
|
| + return EC;
|
| }
|
| - return false;
|
| + return std::error_code();
|
| }
|
|
|
| //===----------------------------------------------------------------------===//
|
| @@ -1694,39 +1795,41 @@ std::error_code NaClBitcodeReader::MaterializeModule(Module *M) {
|
| return std::error_code();
|
| }
|
|
|
| -bool NaClBitcodeReader::InitStream() {
|
| - if (LazyStreamer) return InitLazyStream();
|
| +std::error_code NaClBitcodeReader::InitStream() {
|
| + if (LazyStreamer)
|
| + return InitLazyStream();
|
| return InitStreamFromBuffer();
|
| }
|
|
|
| -bool NaClBitcodeReader::InitStreamFromBuffer() {
|
| +std::error_code NaClBitcodeReader::InitStreamFromBuffer() {
|
| const unsigned char *BufPtr = (const unsigned char*)Buffer->getBufferStart();
|
| const unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
|
|
|
| if (Buffer->getBufferSize() & 3)
|
| - return Error("Bitcode stream should be a multiple of 4 bytes in length");
|
| + return Error(InvalidBitstream,
|
| + "Bitcode stream should be a multiple of 4 bytes in length");
|
|
|
| if (Header.Read(BufPtr, BufEnd))
|
| - return Error(Header.Unsupported());
|
| + return Error(InvalidBitstream, Header.Unsupported());
|
|
|
| StreamFile.reset(new NaClBitstreamReader(BufPtr, BufEnd));
|
| Stream.init(*StreamFile);
|
|
|
| if (AcceptHeader())
|
| - return Error(Header.Unsupported());
|
| - return false;
|
| + return Error(InvalidBitstream, Header.Unsupported());
|
| + return std::error_code();
|
| }
|
|
|
| -bool NaClBitcodeReader::InitLazyStream() {
|
| +std::error_code NaClBitcodeReader::InitLazyStream() {
|
| if (Header.Read(LazyStreamer))
|
| - return Error(Header.Unsupported());
|
| + return Error(InvalidBitstream, Header.Unsupported());
|
|
|
| StreamFile.reset(new NaClBitstreamReader(LazyStreamer,
|
| Header.getHeaderSize()));
|
| Stream.init(*StreamFile);
|
| if (AcceptHeader())
|
| - return Error(Header.Unsupported());
|
| - return false;
|
| + return Error(InvalidBitstream, Header.Unsupported());
|
| + return std::error_code();
|
| }
|
|
|
| //===----------------------------------------------------------------------===//
|
| @@ -1735,20 +1838,17 @@ bool NaClBitcodeReader::InitLazyStream() {
|
|
|
| /// getNaClLazyBitcodeModule - lazy function-at-a-time loading from a file.
|
| ///
|
| -Module *llvm::getNaClLazyBitcodeModule(MemoryBuffer *Buffer,
|
| - LLVMContext& Context,
|
| - std::string *ErrMsg,
|
| - bool AcceptSupportedOnly) {
|
| +ErrorOr<Module *> llvm::getNaClLazyBitcodeModule(
|
| + MemoryBuffer *Buffer, LLVMContext& Context, raw_ostream *Verbose,
|
| + bool AcceptSupportedOnly) {
|
| Module *M = new Module(Buffer->getBufferIdentifier(), Context);
|
| NaClBitcodeReader *R =
|
| - new NaClBitcodeReader(Buffer, Context, AcceptSupportedOnly);
|
| + new NaClBitcodeReader(Buffer, Context, Verbose, AcceptSupportedOnly);
|
| M->setMaterializer(R);
|
| - if (R->ParseBitcodeInto(M)) {
|
| - if (ErrMsg)
|
| - *ErrMsg = R->getErrorString();
|
| -
|
| + if (std::error_code EC = R->ParseBitcodeInto(M)) {
|
| + R->releaseBuffer(); // Never take ownership on error.
|
| delete M; // Also deletes R.
|
| - return 0;
|
| + return EC;
|
| }
|
|
|
| return M;
|
| @@ -1758,17 +1858,19 @@ Module *llvm::getNaClLazyBitcodeModule(MemoryBuffer *Buffer,
|
| Module *llvm::getNaClStreamedBitcodeModule(const std::string &name,
|
| StreamingMemoryObject *Streamer,
|
| LLVMContext &Context,
|
| + raw_ostream *Verbose,
|
| std::string *ErrMsg,
|
| bool AcceptSupportedOnly) {
|
| Module *M = new Module(name, Context);
|
| NaClBitcodeReader *R =
|
| - new NaClBitcodeReader(Streamer, Context, AcceptSupportedOnly);
|
| + new NaClBitcodeReader(Streamer, Context, Verbose,
|
| + AcceptSupportedOnly);
|
| M->setMaterializer(R);
|
| - if (R->ParseBitcodeInto(M)) {
|
| + if (std::error_code EC = R->ParseBitcodeInto(M)) {
|
| if (ErrMsg)
|
| - *ErrMsg = R->getErrorString();
|
| + *ErrMsg = EC.message();
|
| delete M; // Also deletes R.
|
| - return 0;
|
| + return nullptr;
|
| }
|
|
|
| return M;
|
| @@ -1776,18 +1878,18 @@ Module *llvm::getNaClStreamedBitcodeModule(const std::string &name,
|
|
|
| /// NaClParseBitcodeFile - Read the specified bitcode file, returning the module.
|
| /// If an error occurs, return null and fill in *ErrMsg if non-null.
|
| -Module *llvm::NaClParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context,
|
| - std::string *ErrMsg,
|
| - bool AcceptSupportedOnly){
|
| - Module *M = getNaClLazyBitcodeModule(Buffer, Context, ErrMsg,
|
| - AcceptSupportedOnly);
|
| - if (!M) return 0;
|
| -
|
| +ErrorOr<Module *> llvm::NaClParseBitcodeFile(
|
| + MemoryBuffer *Buffer, LLVMContext& Context, raw_ostream *Verbose,
|
| + bool AcceptSupportedOnly){
|
| + ErrorOr<Module *> ModuleOrErr =
|
| + getNaClLazyBitcodeModule(Buffer, Context, Verbose, AcceptSupportedOnly);
|
| + if (!ModuleOrErr)
|
| + return ModuleOrErr;
|
| + Module *M = ModuleOrErr.get();
|
| // Read in the entire module, and destroy the NaClBitcodeReader.
|
| if (std::error_code EC = M->materializeAllPermanently()) {
|
| - *ErrMsg = EC.message();
|
| delete M;
|
| - return 0;
|
| + return EC;
|
| }
|
|
|
| // TODO: Restore the use-lists to the in-memory state when the bitcode was
|
|
|