mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-13 07:00:59 +00:00
For PR797:
Make the Bytecode Reader use setjmp/longjump instead of exceptions to handle errors. The alternative was even uglier than setjmp/longjump as it would impact the interface and workings of nearly every function in the reader. llvm-svn: 29819
This commit is contained in:
parent
88b3207059
commit
d00c37651a
@ -51,13 +51,10 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Provide some details on error
|
// Provide some details on error
|
||||||
inline void BytecodeReader::error(std::string err) {
|
inline void BytecodeReader::error(const std::string& err) {
|
||||||
err += " (Vers=" ;
|
ErrorMsg = err + " (Vers=" + itostr(RevisionNum) + ", Pos="
|
||||||
err += itostr(RevisionNum) ;
|
+ itostr(At-MemStart) + ")";
|
||||||
err += ", Pos=" ;
|
longjmp(context,1);
|
||||||
err += itostr(At-MemStart);
|
|
||||||
err += ")";
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -470,7 +467,8 @@ Value * BytecodeReader::getValue(unsigned type, unsigned oNum, bool Create) {
|
|||||||
ForwardReferences.insert(I, std::make_pair(KeyValue, Val));
|
ForwardReferences.insert(I, std::make_pair(KeyValue, Val));
|
||||||
return Val;
|
return Val;
|
||||||
}
|
}
|
||||||
throw "Can't create placeholder for value of type slot #" + utostr(type);
|
error("Can't create placeholder for value of type slot #" + utostr(type));
|
||||||
|
return 0; // just silence warning, error calls longjmp
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is just like getValue, but when a compaction table is in use, it
|
/// This is just like getValue, but when a compaction table is in use, it
|
||||||
@ -718,12 +716,12 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
|
|||||||
}
|
}
|
||||||
case Instruction::ExtractElement: {
|
case Instruction::ExtractElement: {
|
||||||
if (Oprnds.size() != 2)
|
if (Oprnds.size() != 2)
|
||||||
throw std::string("Invalid extractelement instruction!");
|
error("Invalid extractelement instruction!");
|
||||||
Value *V1 = getValue(iType, Oprnds[0]);
|
Value *V1 = getValue(iType, Oprnds[0]);
|
||||||
Value *V2 = getValue(Type::UIntTyID, Oprnds[1]);
|
Value *V2 = getValue(Type::UIntTyID, Oprnds[1]);
|
||||||
|
|
||||||
if (!ExtractElementInst::isValidOperands(V1, V2))
|
if (!ExtractElementInst::isValidOperands(V1, V2))
|
||||||
throw std::string("Invalid extractelement instruction!");
|
error("Invalid extractelement instruction!");
|
||||||
|
|
||||||
Result = new ExtractElementInst(V1, V2);
|
Result = new ExtractElementInst(V1, V2);
|
||||||
break;
|
break;
|
||||||
@ -731,28 +729,28 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
|
|||||||
case Instruction::InsertElement: {
|
case Instruction::InsertElement: {
|
||||||
const PackedType *PackedTy = dyn_cast<PackedType>(InstTy);
|
const PackedType *PackedTy = dyn_cast<PackedType>(InstTy);
|
||||||
if (!PackedTy || Oprnds.size() != 3)
|
if (!PackedTy || Oprnds.size() != 3)
|
||||||
throw std::string("Invalid insertelement instruction!");
|
error("Invalid insertelement instruction!");
|
||||||
|
|
||||||
Value *V1 = getValue(iType, Oprnds[0]);
|
Value *V1 = getValue(iType, Oprnds[0]);
|
||||||
Value *V2 = getValue(getTypeSlot(PackedTy->getElementType()), Oprnds[1]);
|
Value *V2 = getValue(getTypeSlot(PackedTy->getElementType()), Oprnds[1]);
|
||||||
Value *V3 = getValue(Type::UIntTyID, Oprnds[2]);
|
Value *V3 = getValue(Type::UIntTyID, Oprnds[2]);
|
||||||
|
|
||||||
if (!InsertElementInst::isValidOperands(V1, V2, V3))
|
if (!InsertElementInst::isValidOperands(V1, V2, V3))
|
||||||
throw std::string("Invalid insertelement instruction!");
|
error("Invalid insertelement instruction!");
|
||||||
Result = new InsertElementInst(V1, V2, V3);
|
Result = new InsertElementInst(V1, V2, V3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instruction::ShuffleVector: {
|
case Instruction::ShuffleVector: {
|
||||||
const PackedType *PackedTy = dyn_cast<PackedType>(InstTy);
|
const PackedType *PackedTy = dyn_cast<PackedType>(InstTy);
|
||||||
if (!PackedTy || Oprnds.size() != 3)
|
if (!PackedTy || Oprnds.size() != 3)
|
||||||
throw std::string("Invalid shufflevector instruction!");
|
error("Invalid shufflevector instruction!");
|
||||||
Value *V1 = getValue(iType, Oprnds[0]);
|
Value *V1 = getValue(iType, Oprnds[0]);
|
||||||
Value *V2 = getValue(iType, Oprnds[1]);
|
Value *V2 = getValue(iType, Oprnds[1]);
|
||||||
const PackedType *EltTy =
|
const PackedType *EltTy =
|
||||||
PackedType::get(Type::UIntTy, PackedTy->getNumElements());
|
PackedType::get(Type::UIntTy, PackedTy->getNumElements());
|
||||||
Value *V3 = getValue(getTypeSlot(EltTy), Oprnds[2]);
|
Value *V3 = getValue(getTypeSlot(EltTy), Oprnds[2]);
|
||||||
if (!ShuffleVectorInst::isValidOperands(V1, V2, V3))
|
if (!ShuffleVectorInst::isValidOperands(V1, V2, V3))
|
||||||
throw std::string("Invalid shufflevector instruction!");
|
error("Invalid shufflevector instruction!");
|
||||||
Result = new ShuffleVectorInst(V1, V2, V3);
|
Result = new ShuffleVectorInst(V1, V2, V3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2403,95 +2401,14 @@ void BytecodeReader::ParseModule() {
|
|||||||
|
|
||||||
/// This function completely parses a bytecode buffer given by the \p Buf
|
/// This function completely parses a bytecode buffer given by the \p Buf
|
||||||
/// and \p Length parameters.
|
/// and \p Length parameters.
|
||||||
void BytecodeReader::ParseBytecode(BufPtr Buf, unsigned Length,
|
bool BytecodeReader::ParseBytecode(BufPtr Buf, unsigned Length,
|
||||||
const std::string &ModuleID) {
|
const std::string &ModuleID,
|
||||||
|
std::string* ErrMsg) {
|
||||||
|
|
||||||
try {
|
/// We handle errors by
|
||||||
RevisionNum = 0;
|
if (setjmp(context)) {
|
||||||
At = MemStart = BlockStart = Buf;
|
// Cleanup after error
|
||||||
MemEnd = BlockEnd = Buf + Length;
|
if (Handler) Handler->handleError(ErrorMsg);
|
||||||
|
|
||||||
// Create the module
|
|
||||||
TheModule = new Module(ModuleID);
|
|
||||||
|
|
||||||
if (Handler) Handler->handleStart(TheModule, Length);
|
|
||||||
|
|
||||||
// Read the four bytes of the signature.
|
|
||||||
unsigned Sig = read_uint();
|
|
||||||
|
|
||||||
// If this is a compressed file
|
|
||||||
if (Sig == ('l' | ('l' << 8) | ('v' << 16) | ('c' << 24))) {
|
|
||||||
|
|
||||||
// Invoke the decompression of the bytecode. Note that we have to skip the
|
|
||||||
// file's magic number which is not part of the compressed block. Hence,
|
|
||||||
// the Buf+4 and Length-4. The result goes into decompressedBlock, a data
|
|
||||||
// member for retention until BytecodeReader is destructed.
|
|
||||||
unsigned decompressedLength = Compressor::decompressToNewBuffer(
|
|
||||||
(char*)Buf+4,Length-4,decompressedBlock);
|
|
||||||
|
|
||||||
// We must adjust the buffer pointers used by the bytecode reader to point
|
|
||||||
// into the new decompressed block. After decompression, the
|
|
||||||
// decompressedBlock will point to a contiguous memory area that has
|
|
||||||
// the decompressed data.
|
|
||||||
At = MemStart = BlockStart = Buf = (BufPtr) decompressedBlock;
|
|
||||||
MemEnd = BlockEnd = Buf + decompressedLength;
|
|
||||||
|
|
||||||
// else if this isn't a regular (uncompressed) bytecode file, then its
|
|
||||||
// and error, generate that now.
|
|
||||||
} else if (Sig != ('l' | ('l' << 8) | ('v' << 16) | ('m' << 24))) {
|
|
||||||
error("Invalid bytecode signature: " + utohexstr(Sig));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell the handler we're starting a module
|
|
||||||
if (Handler) Handler->handleModuleBegin(ModuleID);
|
|
||||||
|
|
||||||
// Get the module block and size and verify. This is handled specially
|
|
||||||
// because the module block/size is always written in long format. Other
|
|
||||||
// blocks are written in short format so the read_block method is used.
|
|
||||||
unsigned Type, Size;
|
|
||||||
Type = read_uint();
|
|
||||||
Size = read_uint();
|
|
||||||
if (Type != BytecodeFormat::ModuleBlockID) {
|
|
||||||
error("Expected Module Block! Type:" + utostr(Type) + ", Size:"
|
|
||||||
+ utostr(Size));
|
|
||||||
}
|
|
||||||
|
|
||||||
// It looks like the darwin ranlib program is broken, and adds trailing
|
|
||||||
// garbage to the end of some bytecode files. This hack allows the bc
|
|
||||||
// reader to ignore trailing garbage on bytecode files.
|
|
||||||
if (At + Size < MemEnd)
|
|
||||||
MemEnd = BlockEnd = At+Size;
|
|
||||||
|
|
||||||
if (At + Size != MemEnd)
|
|
||||||
error("Invalid Top Level Block Length! Type:" + utostr(Type)
|
|
||||||
+ ", Size:" + utostr(Size));
|
|
||||||
|
|
||||||
// Parse the module contents
|
|
||||||
this->ParseModule();
|
|
||||||
|
|
||||||
// Check for missing functions
|
|
||||||
if (hasFunctions())
|
|
||||||
error("Function expected, but bytecode stream ended!");
|
|
||||||
|
|
||||||
// Look for intrinsic functions to upgrade, upgrade them, and save the
|
|
||||||
// mapping from old function to new for use later when instructions are
|
|
||||||
// converted.
|
|
||||||
for (Module::iterator FI = TheModule->begin(), FE = TheModule->end();
|
|
||||||
FI != FE; ++FI)
|
|
||||||
if (Function* newF = UpgradeIntrinsicFunction(FI)) {
|
|
||||||
upgradedFunctions.insert(std::make_pair(FI, newF));
|
|
||||||
FI->setName("");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell the handler we're done with the module
|
|
||||||
if (Handler)
|
|
||||||
Handler->handleModuleEnd(ModuleID);
|
|
||||||
|
|
||||||
// Tell the handler we're finished the parse
|
|
||||||
if (Handler) Handler->handleFinish();
|
|
||||||
|
|
||||||
} catch (std::string& errstr) {
|
|
||||||
if (Handler) Handler->handleError(errstr);
|
|
||||||
freeState();
|
freeState();
|
||||||
delete TheModule;
|
delete TheModule;
|
||||||
TheModule = 0;
|
TheModule = 0;
|
||||||
@ -2499,19 +2416,98 @@ void BytecodeReader::ParseBytecode(BufPtr Buf, unsigned Length,
|
|||||||
::free(decompressedBlock);
|
::free(decompressedBlock);
|
||||||
decompressedBlock = 0;
|
decompressedBlock = 0;
|
||||||
}
|
}
|
||||||
throw;
|
// Set caller's error message, if requested
|
||||||
} catch (...) {
|
if (ErrMsg)
|
||||||
std::string msg("Unknown Exception Occurred");
|
*ErrMsg = ErrorMsg;
|
||||||
if (Handler) Handler->handleError(msg);
|
// Indicate an error occurred
|
||||||
freeState();
|
return true;
|
||||||
delete TheModule;
|
|
||||||
TheModule = 0;
|
|
||||||
if (decompressedBlock != 0) {
|
|
||||||
::free(decompressedBlock);
|
|
||||||
decompressedBlock = 0;
|
|
||||||
}
|
|
||||||
throw msg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RevisionNum = 0;
|
||||||
|
At = MemStart = BlockStart = Buf;
|
||||||
|
MemEnd = BlockEnd = Buf + Length;
|
||||||
|
|
||||||
|
// Create the module
|
||||||
|
TheModule = new Module(ModuleID);
|
||||||
|
|
||||||
|
if (Handler) Handler->handleStart(TheModule, Length);
|
||||||
|
|
||||||
|
// Read the four bytes of the signature.
|
||||||
|
unsigned Sig = read_uint();
|
||||||
|
|
||||||
|
// If this is a compressed file
|
||||||
|
if (Sig == ('l' | ('l' << 8) | ('v' << 16) | ('c' << 24))) {
|
||||||
|
|
||||||
|
// Invoke the decompression of the bytecode. Note that we have to skip the
|
||||||
|
// file's magic number which is not part of the compressed block. Hence,
|
||||||
|
// the Buf+4 and Length-4. The result goes into decompressedBlock, a data
|
||||||
|
// member for retention until BytecodeReader is destructed.
|
||||||
|
unsigned decompressedLength = Compressor::decompressToNewBuffer(
|
||||||
|
(char*)Buf+4,Length-4,decompressedBlock);
|
||||||
|
|
||||||
|
// We must adjust the buffer pointers used by the bytecode reader to point
|
||||||
|
// into the new decompressed block. After decompression, the
|
||||||
|
// decompressedBlock will point to a contiguous memory area that has
|
||||||
|
// the decompressed data.
|
||||||
|
At = MemStart = BlockStart = Buf = (BufPtr) decompressedBlock;
|
||||||
|
MemEnd = BlockEnd = Buf + decompressedLength;
|
||||||
|
|
||||||
|
// else if this isn't a regular (uncompressed) bytecode file, then its
|
||||||
|
// and error, generate that now.
|
||||||
|
} else if (Sig != ('l' | ('l' << 8) | ('v' << 16) | ('m' << 24))) {
|
||||||
|
error("Invalid bytecode signature: " + utohexstr(Sig));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell the handler we're starting a module
|
||||||
|
if (Handler) Handler->handleModuleBegin(ModuleID);
|
||||||
|
|
||||||
|
// Get the module block and size and verify. This is handled specially
|
||||||
|
// because the module block/size is always written in long format. Other
|
||||||
|
// blocks are written in short format so the read_block method is used.
|
||||||
|
unsigned Type, Size;
|
||||||
|
Type = read_uint();
|
||||||
|
Size = read_uint();
|
||||||
|
if (Type != BytecodeFormat::ModuleBlockID) {
|
||||||
|
error("Expected Module Block! Type:" + utostr(Type) + ", Size:"
|
||||||
|
+ utostr(Size));
|
||||||
|
}
|
||||||
|
|
||||||
|
// It looks like the darwin ranlib program is broken, and adds trailing
|
||||||
|
// garbage to the end of some bytecode files. This hack allows the bc
|
||||||
|
// reader to ignore trailing garbage on bytecode files.
|
||||||
|
if (At + Size < MemEnd)
|
||||||
|
MemEnd = BlockEnd = At+Size;
|
||||||
|
|
||||||
|
if (At + Size != MemEnd)
|
||||||
|
error("Invalid Top Level Block Length! Type:" + utostr(Type)
|
||||||
|
+ ", Size:" + utostr(Size));
|
||||||
|
|
||||||
|
// Parse the module contents
|
||||||
|
this->ParseModule();
|
||||||
|
|
||||||
|
// Check for missing functions
|
||||||
|
if (hasFunctions())
|
||||||
|
error("Function expected, but bytecode stream ended!");
|
||||||
|
|
||||||
|
// Look for intrinsic functions to upgrade, upgrade them, and save the
|
||||||
|
// mapping from old function to new for use later when instructions are
|
||||||
|
// converted.
|
||||||
|
for (Module::iterator FI = TheModule->begin(), FE = TheModule->end();
|
||||||
|
FI != FE; ++FI)
|
||||||
|
if (Function* newF = UpgradeIntrinsicFunction(FI)) {
|
||||||
|
upgradedFunctions.insert(std::make_pair(FI, newF));
|
||||||
|
FI->setName("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell the handler we're done with the module
|
||||||
|
if (Handler)
|
||||||
|
Handler->handleModuleEnd(ModuleID);
|
||||||
|
|
||||||
|
// Tell the handler we're finished the parse
|
||||||
|
if (Handler) Handler->handleFinish();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "llvm/Bytecode/Analyzer.h"
|
#include "llvm/Bytecode/Analyzer.h"
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
@ -136,11 +137,13 @@ public:
|
|||||||
/// @name Methods
|
/// @name Methods
|
||||||
/// @{
|
/// @{
|
||||||
public:
|
public:
|
||||||
|
/// @returns true if an error occurred
|
||||||
/// @brief Main interface to parsing a bytecode buffer.
|
/// @brief Main interface to parsing a bytecode buffer.
|
||||||
void ParseBytecode(
|
bool ParseBytecode(
|
||||||
const unsigned char *Buf, ///< Beginning of the bytecode buffer
|
const unsigned char *Buf, ///< Beginning of the bytecode buffer
|
||||||
unsigned Length, ///< Length of the bytecode buffer
|
unsigned Length, ///< Length of the bytecode buffer
|
||||||
const std::string &ModuleID ///< An identifier for the module constructed.
|
const std::string &ModuleID, ///< An identifier for the module constructed.
|
||||||
|
std::string* ErrMsg = 0 ///< Optional place for error message
|
||||||
);
|
);
|
||||||
|
|
||||||
/// @brief Parse all function bodies
|
/// @brief Parse all function bodies
|
||||||
@ -260,6 +263,8 @@ protected:
|
|||||||
/// @name Data
|
/// @name Data
|
||||||
/// @{
|
/// @{
|
||||||
private:
|
private:
|
||||||
|
std::string ErrorMsg; ///< A place to hold an error message through longjmp
|
||||||
|
jmp_buf context; ///< Where to return to if an error occurs.
|
||||||
char* decompressedBlock; ///< Result of decompression
|
char* decompressedBlock; ///< Result of decompression
|
||||||
BufPtr MemStart; ///< Start of the memory buffer
|
BufPtr MemStart; ///< Start of the memory buffer
|
||||||
BufPtr MemEnd; ///< End of the memory buffer
|
BufPtr MemEnd; ///< End of the memory buffer
|
||||||
@ -487,7 +492,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void error(std::string errmsg);
|
inline void error(const std::string& errmsg);
|
||||||
|
|
||||||
BytecodeReader(const BytecodeReader &); // DO NOT IMPLEMENT
|
BytecodeReader(const BytecodeReader &); // DO NOT IMPLEMENT
|
||||||
void operator=(const BytecodeReader &); // DO NOT IMPLEMENT
|
void operator=(const BytecodeReader &); // DO NOT IMPLEMENT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user