[llvm-commits] CVS: llvm/lib/Bytecode/Reader/Reader.h Reader.cpp

Reid Spencer reid at x10sys.com
Tue Aug 22 09:09:33 PDT 2006



Changes in directory llvm/lib/Bytecode/Reader:

Reader.h updated: 1.30 -> 1.31
Reader.cpp updated: 1.194 -> 1.195
---
Log message:

For PR797: http://llvm.org/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.


---
Diffs of the changes:  (+119 -118)

 Reader.cpp |  226 +++++++++++++++++++++++++++++--------------------------------
 Reader.h   |   11 ++
 2 files changed, 119 insertions(+), 118 deletions(-)


Index: llvm/lib/Bytecode/Reader/Reader.h
diff -u llvm/lib/Bytecode/Reader/Reader.h:1.30 llvm/lib/Bytecode/Reader/Reader.h:1.31
--- llvm/lib/Bytecode/Reader/Reader.h:1.30	Fri Jul  7 01:06:06 2006
+++ llvm/lib/Bytecode/Reader/Reader.h	Tue Aug 22 11:09:19 2006
@@ -24,6 +24,7 @@
 #include "llvm/Bytecode/Analyzer.h"
 #include <utility>
 #include <map>
+#include <setjmp.h>
 
 namespace llvm {
 
@@ -136,11 +137,13 @@
 /// @name Methods
 /// @{
 public:
+  /// @returns true if an error occurred
   /// @brief Main interface to parsing a bytecode buffer.
-  void ParseBytecode(
+  bool ParseBytecode(
      const unsigned char *Buf,    ///< Beginning 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
@@ -260,6 +263,8 @@
 /// @name Data
 /// @{
 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
   BufPtr MemStart;     ///< Start of the memory buffer
   BufPtr MemEnd;       ///< End of the memory buffer
@@ -487,7 +492,7 @@
     }
   }
 
-  inline void error(std::string errmsg);
+  inline void error(const std::string& errmsg);
 
   BytecodeReader(const BytecodeReader &);  // DO NOT IMPLEMENT
   void operator=(const BytecodeReader &);  // DO NOT IMPLEMENT


Index: llvm/lib/Bytecode/Reader/Reader.cpp
diff -u llvm/lib/Bytecode/Reader/Reader.cpp:1.194 llvm/lib/Bytecode/Reader/Reader.cpp:1.195
--- llvm/lib/Bytecode/Reader/Reader.cpp:1.194	Fri May 26 13:42:34 2006
+++ llvm/lib/Bytecode/Reader/Reader.cpp	Tue Aug 22 11:09:19 2006
@@ -51,13 +51,10 @@
 }
 
 // Provide some details on error
-inline void BytecodeReader::error(std::string err) {
-  err +=  " (Vers=" ;
-  err += itostr(RevisionNum) ;
-  err += ", Pos=" ;
-  err += itostr(At-MemStart);
-  err += ")";
-  throw err;
+inline void BytecodeReader::error(const std::string& err) {
+  ErrorMsg = err + " (Vers=" + itostr(RevisionNum) + ", Pos=" 
+    + itostr(At-MemStart) + ")";
+  longjmp(context,1);
 }
 
 //===----------------------------------------------------------------------===//
@@ -470,7 +467,8 @@
     ForwardReferences.insert(I, std::make_pair(KeyValue, 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
@@ -718,12 +716,12 @@
   }
   case Instruction::ExtractElement: {
     if (Oprnds.size() != 2)
-      throw std::string("Invalid extractelement instruction!");
+      error("Invalid extractelement instruction!");
     Value *V1 = getValue(iType, Oprnds[0]);
     Value *V2 = getValue(Type::UIntTyID, Oprnds[1]);
     
     if (!ExtractElementInst::isValidOperands(V1, V2))
-      throw std::string("Invalid extractelement instruction!");
+      error("Invalid extractelement instruction!");
 
     Result = new ExtractElementInst(V1, V2);
     break;
@@ -731,28 +729,28 @@
   case Instruction::InsertElement: {
     const PackedType *PackedTy = dyn_cast<PackedType>(InstTy);
     if (!PackedTy || Oprnds.size() != 3)
-      throw std::string("Invalid insertelement instruction!");
+      error("Invalid insertelement instruction!");
     
     Value *V1 = getValue(iType, Oprnds[0]);
     Value *V2 = getValue(getTypeSlot(PackedTy->getElementType()), Oprnds[1]);
     Value *V3 = getValue(Type::UIntTyID, Oprnds[2]);
       
     if (!InsertElementInst::isValidOperands(V1, V2, V3))
-      throw std::string("Invalid insertelement instruction!");
+      error("Invalid insertelement instruction!");
     Result = new InsertElementInst(V1, V2, V3);
     break;
   }
   case Instruction::ShuffleVector: {
     const PackedType *PackedTy = dyn_cast<PackedType>(InstTy);
     if (!PackedTy || Oprnds.size() != 3)
-      throw std::string("Invalid shufflevector instruction!");
+      error("Invalid shufflevector instruction!");
     Value *V1 = getValue(iType, Oprnds[0]);
     Value *V2 = getValue(iType, Oprnds[1]);
     const PackedType *EltTy = 
       PackedType::get(Type::UIntTy, PackedTy->getNumElements());
     Value *V3 = getValue(getTypeSlot(EltTy), Oprnds[2]);
     if (!ShuffleVectorInst::isValidOperands(V1, V2, V3))
-      throw std::string("Invalid shufflevector instruction!");
+      error("Invalid shufflevector instruction!");
     Result = new ShuffleVectorInst(V1, V2, V3);
     break;
   }
@@ -2403,95 +2401,14 @@
 
 /// This function completely parses a bytecode buffer given by the \p Buf
 /// and \p Length parameters.
-void BytecodeReader::ParseBytecode(BufPtr Buf, unsigned Length,
-                                   const std::string &ModuleID) {
-
-  try {
-    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();
-
-  } catch (std::string& errstr) {
-    if (Handler) Handler->handleError(errstr);
+bool BytecodeReader::ParseBytecode(BufPtr Buf, unsigned Length,
+                                   const std::string &ModuleID,
+                                   std::string* ErrMsg) {
+
+  /// We handle errors by
+  if (setjmp(context)) {
+    // Cleanup after error
+    if (Handler) Handler->handleError(ErrorMsg);
     freeState();
     delete TheModule;
     TheModule = 0;
@@ -2499,19 +2416,98 @@
       ::free(decompressedBlock);
       decompressedBlock = 0;
     }
-    throw;
-  } catch (...) {
-    std::string msg("Unknown Exception Occurred");
-    if (Handler) Handler->handleError(msg);
-    freeState();
-    delete TheModule;
-    TheModule = 0;
-    if (decompressedBlock != 0) {
-      ::free(decompressedBlock);
-      decompressedBlock = 0;
+    // Set caller's error message, if requested
+    if (ErrMsg)
+      *ErrMsg = ErrorMsg;
+    // Indicate an error occurred
+    return true;
+  }
+
+  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("");
     }
-    throw msg;
-  }
+
+  // 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;
+
 }
 
 //===----------------------------------------------------------------------===//






More information about the llvm-commits mailing list