Chromium Code Reviews| 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..d526e9feb9eeee679082d95569522fcb8d7ab2e5 100644 |
| --- a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp |
| +++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp |
| @@ -116,6 +116,45 @@ 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::InvalidBBForInstruction: |
| + return "No basic block for instruction"; |
| + case NaClBitcodeReader::InvalidBitstream: |
| + return "Error in bitstream format"; |
| + case NaClBitcodeReader::InvalidConstantReference: |
| + return "Bad constant reference"; |
| + 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::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"; |
| + case NaClBitcodeReader::NoFunctionInStream: |
| + return "Unable to find function in bitcode stream."; |
| + default: |
| + return "Unknown bitsteam error"; |
|
JF
2014/12/02 00:49:04
I wouldn't put a default here: the compiler will w
Karl
2014/12/03 18:32:09
Done.
|
| + } |
| + } |
|
JF
2014/12/02 00:49:04
Put llvm_unreachable here instead (like BitcodeRea
Karl
2014/12/03 18:32:09
Done.
|
| +}; |
| +} // end of anonomous namespace. |
| + |
| +const std::error_category &NaClBitcodeReader::BitcodeErrorCategory() { |
| + static NaClBitcodeErrorCategoryType ErrCat; |
|
JF
2014/12/02 00:49:03
BitcodeReader.cpp uses a ManagedStatic instead of
Karl
2014/12/03 18:32:09
Not in our local version. Waiting for merge?
|
| + return ErrCat; |
| +} |
| + |
| Type *NaClBitcodeReader::getTypeByID(unsigned ID) { |
| // The type table size is always specified correctly. |
| if (ID >= TypeList.size()) |
| @@ -135,20 +174,27 @@ Type *NaClBitcodeReader::getTypeByID(unsigned ID) { |
| //===----------------------------------------------------------------------===// |
| -bool NaClBitcodeReader::ParseTypeTable() { |
| +std::error_code NaClBitcodeReader::Error(ErrorType E, |
| + const std::string &Message) const { |
| + if (Verbose) |
| + errs() << "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(MalformedBlock, "Malformed block record"); |
|
jvoung (off chromium)
2014/12/01 23:23:49
similar, InvalidRecord or MalformedBlock?
Karl
2014/12/03 18:32:09
Changed to InvalidRecord.
|
| - 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 +206,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 +227,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 +277,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 +357,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 +374,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 +390,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 +410,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 +426,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 +435,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 +456,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 +477,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 +491,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 +506,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 +529,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 +547,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 +563,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 +578,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 +593,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 +608,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(MalformedBlock, "Malformed block record"); |
|
jvoung (off chromium)
2014/12/01 23:23:49
Sometimes errors in EnterSubBlock are InvalidRecor
Karl
2014/12/03 18:32:09
Done.
|
| 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 +639,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 +655,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 +667,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 +680,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 +696,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 +718,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 +747,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 +756,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(NaClBitcodeReader::MalformedBlock, |
|
jvoung (off chromium)
2014/12/01 23:23:49
Upstream they have a separate error code for this.
Karl
2014/12/03 18:32:09
Changed to match upstream.
|
| + "Insufficient function protos"); |
| Function *Fn = FunctionsWithBodies.back(); |
| FunctionsWithBodies.pop_back(); |
| @@ -701,12 +778,12 @@ bool NaClBitcodeReader::RememberAndSkipFunctionBody() { |
| // Skip over the function block for now. |
| if (Stream.SkipBlock()) |
| - return Error("Malformed block record"); |
| + return Error(MalformedBlock, "Malformed block record"); |
| 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 +797,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 +854,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 +869,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 +880,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 +907,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 +924,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 +943,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 +992,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 +1011,66 @@ 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(InvalidRecord, "Malformed block record"); |
| 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(InvalidBBForInstruction, |
| + "Instruction with no BB, can't install"); |
| } |
| BB->getInstList().push_back(I); |
| - return false; |
| + return std::error_code(); |
| } |
| CastInst * |
| @@ -1042,10 +1125,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 +1147,27 @@ 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(InvalidRecord, "Malformed block record"); |
|
jvoung (off chromium)
2014/12/01 23:23:49
If these are all InvalidRecord, maybe the verbose
Karl
2014/12/03 18:32:09
Upstream uses InvalidRecord if SkipBlock fails. Ad
|
| 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 +1191,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 +1215,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 +1231,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 +1269,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 +1279,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 +1296,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 +1312,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 +1337,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 +1346,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 +1370,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 +1391,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 +1423,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 +1439,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 +1453,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 +1470,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 +1485,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"); |
| + return Error(InvalidType, "Invalid type for load instruction"); |
| Op = ConvertOpToType(Op, T->getPointerTo(), CurBBNo); |
| - if (Op == 0) return true; |
| + if (Op == 0) |
|
jvoung (off chromium)
2014/12/01 23:23:49
nullptr instead of 0.
Actually, n/m. It may be be
Karl
2014/12/03 18:32:09
In general, I agree that we should delay. However,
|
| + return Error(InvalidTypeForValue, "Can't convert cast to type"); |
| I = new LoadInst(Op, "", false, (1 << Record[OpNum]) >> 1); |
| break; |
| } |
| @@ -1414,7 +1504,7 @@ 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); |
|
jvoung (off chromium)
2014/12/01 23:23:49
For loads, the code checks that ConvertOpToType re
Karl
2014/12/03 18:32:09
Good point. Adding test.
|
| I = new StoreInst(Val, Ptr, false, (1 << Record[OpNum]) >> 1); |
| @@ -1427,14 +1517,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 +1539,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 +1576,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 +1586,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 +1641,7 @@ OutOfRecordLoop: |
| delete A; |
| } |
| } |
| - return Error("Never resolved value found in function!"); |
| + return Error(InvalidValue, "Never resolved value found in function!"); |
| } |
| } |
| @@ -1558,20 +1649,22 @@ 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(NoFunctionInStream, "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 +1787,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 +1830,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, bool VerboseErrors, |
| + bool AcceptSupportedOnly) { |
| Module *M = new Module(Buffer->getBufferIdentifier(), Context); |
| NaClBitcodeReader *R = |
| - new NaClBitcodeReader(Buffer, Context, AcceptSupportedOnly); |
| + new NaClBitcodeReader(Buffer, Context, VerboseErrors, 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 +1850,19 @@ Module *llvm::getNaClLazyBitcodeModule(MemoryBuffer *Buffer, |
| Module *llvm::getNaClStreamedBitcodeModule(const std::string &name, |
| StreamingMemoryObject *Streamer, |
| LLVMContext &Context, |
| + bool VerboseErrors, |
| std::string *ErrMsg, |
| bool AcceptSupportedOnly) { |
| Module *M = new Module(name, Context); |
| NaClBitcodeReader *R = |
| - new NaClBitcodeReader(Streamer, Context, AcceptSupportedOnly); |
| + new NaClBitcodeReader(Streamer, Context, VerboseErrors, |
| + 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 +1870,19 @@ 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, bool VerboseErrors, |
| + bool AcceptSupportedOnly){ |
| + ErrorOr<Module *> ModuleOrErr = |
| + getNaClLazyBitcodeModule(Buffer, Context, VerboseErrors, |
| + 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 |