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 |