diff --git a/llvm/lib/Bytecode/Reader/Reader.cpp b/llvm/lib/Bytecode/Reader/Reader.cpp
new file mode 100644
index 0000000..c3f4c90
--- /dev/null
+++ b/llvm/lib/Bytecode/Reader/Reader.cpp
@@ -0,0 +1,478 @@
+//===- Reader.cpp - Code to read bytecode files -----------------------------===
+//
+// This library implements the functionality defined in llvm/Bytecode/Reader.h
+//
+// Note that this library should be as fast as possible, reentrant, and 
+// threadsafe!!
+//
+// TODO: Make error message outputs be configurable depending on an option?
+// TODO: Allow passing in an option to ignore the symbol table
+//
+//===------------------------------------------------------------------------===
+
+#include "llvm/Bytecode/Reader.h"
+#include "llvm/Bytecode/Format.h"
+#include "llvm/Module.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/ConstPoolVals.h"
+#include "llvm/iOther.h"
+#include "ReaderInternals.h"
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <algorithm>
+
+bool BytecodeParser::getTypeSlot(const Type *Ty, unsigned &Slot) {
+  if (Ty->isPrimitiveType()) {
+    Slot = Ty->getPrimitiveID();
+  } else {
+    TypeMapType::iterator I = TypeMap.find(Ty);
+    if (I == TypeMap.end()) return true;   // Didn't find type!
+    Slot = I->second;
+  }
+  //cerr << "getTypeSlot '" << Ty->getName() << "' = " << Slot << endl;
+  return false;
+}
+
+const Type *BytecodeParser::getType(unsigned ID) {
+  const Type *T = Type::getPrimitiveType((Type::PrimitiveID)ID);
+  if (T) return T;
+  
+  //cerr << "Looking up Type ID: " << ID << endl;
+
+  const Value *D = getValue(Type::TypeTy, ID, false);
+  if (D == 0) return 0;
+
+  assert(D->getType() == Type::TypeTy &&
+	 D->getValueType() == Value::ConstantVal);
+
+
+  return ((const ConstPoolType*)D)->getValue();;
+}
+
+bool BytecodeParser::insertValue(Value *Def, vector<ValueList> &ValueTab) {
+  unsigned type;
+  if (getTypeSlot(Def->getType(), type)) return true;
+ 
+  if (ValueTab.size() <= type)
+    ValueTab.resize(type+1, ValueList());
+
+  //cerr << "insertValue Values[" << type << "][" << ValueTab[type].size() 
+  //     << "] = " << Def << endl;
+
+  if (type == Type::TypeTyID && Def->getValueType() == Value::ConstantVal) {
+    const Type *Ty = ((const ConstPoolType*)Def)->getValue();
+    unsigned ValueOffset = FirstDerivedTyID;
+
+    if (&ValueTab == &Values)    // Take into consideration module level types
+      ValueOffset += ModuleValues[type].size();
+
+    if (TypeMap.find(Ty) == TypeMap.end())
+      TypeMap[Ty] = ValueTab[type].size()+ValueOffset;
+  }
+
+  ValueTab[type].push_back(Def);
+
+  return false;
+}
+
+Value *BytecodeParser::getValue(const Type *Ty, unsigned oNum, bool Create) {
+  unsigned Num = oNum;
+  unsigned type;   // The type plane it lives in...
+
+  if (getTypeSlot(Ty, type)) return 0; // TODO: true
+
+  if (type == Type::TypeTyID) {  // The 'type' plane has implicit values
+    const Type *T = Type::getPrimitiveType((Type::PrimitiveID)Num);
+    if (T) return (Value*)T;   // Asked for a primitive type...
+
+    // Otherwise, derived types need offset...
+    Num -= FirstDerivedTyID;
+  }
+
+  if (ModuleValues.size() > type) {
+    if (ModuleValues[type].size() > Num)
+      return ModuleValues[type][Num];
+    Num -= ModuleValues[type].size();
+  }
+
+  if (Values.size() > type && Values[type].size() > Num)
+    return Values[type][Num];
+
+  if (!Create) return 0;  // Do not create a placeholder?
+
+  Value *d = 0;
+  switch (Ty->getPrimitiveID()) {
+  case Type::LabelTyID: d = new    BBPHolder(Ty, oNum); break;
+  case Type::MethodTyID:
+    cerr << "Creating method pholder! : " << type << ":" << oNum << " " 
+	 << Ty->getName() << endl;
+    d = new MethPHolder(Ty, oNum);
+    insertValue(d, LateResolveModuleValues);
+    return d;
+  default:                   d = new   DefPHolder(Ty, oNum); break;
+  }
+
+  assert(d != 0 && "How did we not make something?");
+  if (insertValue(d, LateResolveValues)) return 0;
+  return d;
+}
+
+bool BytecodeParser::postResolveValues(ValueTable &ValTab) {
+  bool Error = false;
+  for (unsigned ty = 0; ty < ValTab.size(); ty++) {
+    ValueList &DL = ValTab[ty];
+    unsigned Size;
+    while ((Size = DL.size())) {
+      unsigned IDNumber = getValueIDNumberFromPlaceHolder(DL[Size-1]);
+
+      Value *D = DL[Size-1];
+      DL.pop_back();
+
+      Value *NewDef = getValue(D->getType(), IDNumber, false);
+      if (NewDef == 0) {
+	Error = true;  // Unresolved thinger
+	cerr << "Unresolvable reference found: <" << D->getType()->getName()
+	     << ">:" << IDNumber << "!\n";
+      } else {
+	// Fixup all of the uses of this placeholder def...
+        D->replaceAllUsesWith(NewDef);
+
+        // Now that all the uses are gone, delete the placeholder...
+        // If we couldn't find a def (error case), then leak a little
+	delete D;  // memory, 'cause otherwise we can't remove all uses!
+      }
+    }
+  }
+
+  return Error;
+}
+
+bool BytecodeParser::ParseBasicBlock(const uchar *&Buf, const uchar *EndBuf, 
+				     BasicBlock *&BB) {
+  BB = new BasicBlock();
+
+  while (Buf < EndBuf) {
+    Instruction *Def;
+    if (ParseInstruction(Buf, EndBuf, Def)) {
+      delete BB;
+      return true;
+    }
+
+    if (Def == 0) { delete BB; return true; }
+    if (insertValue(Def, Values)) { delete BB; return true; }
+
+    BB->getInstList().push_back(Def);
+  }
+
+  return false;
+}
+
+bool BytecodeParser::ParseSymbolTable(const uchar *&Buf, const uchar *EndBuf) {
+  while (Buf < EndBuf) {
+    // Symtab block header: [num entries][type id number]
+    unsigned NumEntries, Typ;
+    if (read_vbr(Buf, EndBuf, NumEntries) ||
+        read_vbr(Buf, EndBuf, Typ)) return true;
+    const Type *Ty = getType(Typ);
+    if (Ty == 0) return true;
+
+    for (unsigned i = 0; i < NumEntries; i++) {
+      // Symtab entry: [def slot #][name]
+      unsigned slot;
+      if (read_vbr(Buf, EndBuf, slot)) return true;
+      string Name;
+      if (read(Buf, EndBuf, Name, false))  // Not aligned...
+	return true;
+
+      Value *D = getValue(Ty, slot, false); // Find mapping...
+      if (D == 0) return true;
+      D->setName(Name);
+    }
+  }
+
+  return Buf > EndBuf;
+}
+
+
+bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf, 
+				 Module *C) {
+  // Clear out the local values table...
+  Values.clear();
+  if (MethodSignatureList.empty()) return true;  // Unexpected method!
+
+  const MethodType *MTy = MethodSignatureList.front().first;
+  unsigned MethSlot = MethodSignatureList.front().second;
+  MethodSignatureList.pop_front();
+  Method *M = new Method(MTy);
+
+  const MethodType::ParamTypes &Params = MTy->getParamTypes();
+  for (MethodType::ParamTypes::const_iterator It = Params.begin();
+       It != Params.end(); It++) {
+    MethodArgument *MA = new MethodArgument(*It);
+    if (insertValue(MA, Values)) { delete M; return true; }
+    M->getArgumentList().push_back(MA);
+  }
+
+  while (Buf < EndBuf) {
+    unsigned Type, Size;
+    const uchar *OldBuf = Buf;
+    if (readBlock(Buf, EndBuf, Type, Size)) { delete M; return true; }
+
+    switch (Type) {
+    case BytecodeFormat::ConstantPool:
+      if (ParseConstantPool(Buf, Buf+Size, M->getConstantPool(), Values)) {
+	cerr << "Error reading constant pool!\n";
+	delete M; return true;
+      }
+      break;
+
+    case BytecodeFormat::BasicBlock: {
+      BasicBlock *BB;
+      if (ParseBasicBlock(Buf, Buf+Size, BB) ||
+	  insertValue(BB, Values)) {
+	cerr << "Error parsing basic block!\n";
+	delete M; return true;                       // Parse error... :(
+      }
+
+      M->getBasicBlocks().push_back(BB);
+      break;
+    }
+
+    case BytecodeFormat::SymbolTable:
+      if (ParseSymbolTable(Buf, Buf+Size)) {
+	cerr << "Error reading method symbol table!\n";
+	delete M; return true;
+      }
+      break;
+
+    default:
+      Buf += Size;
+      if (OldBuf > Buf) return true; // Wrap around!
+      break;
+    }
+    if (align32(Buf, EndBuf)) {
+      delete M;    // Malformed bc file, read past end of block.
+      return true;
+    }
+  }
+
+  if (postResolveValues(LateResolveValues) ||
+      postResolveValues(LateResolveModuleValues)) {
+    delete M; return true;     // Unresolvable references!
+  }
+
+  Value *MethPHolder = getValue(MTy, MethSlot, false);
+  assert(MethPHolder && "Something is broken no placeholder found!");
+  assert(MethPHolder->getValueType() == Value::MethodVal && "Not a method?");
+
+  unsigned type;  // Type slot
+  assert(!getTypeSlot(MTy, type) && "How can meth type not exist?");
+  getTypeSlot(MTy, type);
+
+  C->getMethodList().push_back(M);
+
+  // Replace placeholder with the real method pointer...
+  ModuleValues[type][MethSlot] = M;
+
+  // If anyone is using the placeholder make them use the real method instead
+  MethPHolder->replaceAllUsesWith(M);
+
+  // We don't need the placeholder anymore!
+  delete MethPHolder;
+
+  return false;
+}
+
+bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
+					  Module *C) {
+
+  if (!MethodSignatureList.empty()) return true;  // Two ModuleGlobal blocks?
+
+  // Read the method signatures for all of the methods that are coming, and 
+  // create fillers in the Value tables.
+  unsigned MethSignature;
+  if (read_vbr(Buf, End, MethSignature)) return true;
+  while (MethSignature != Type::VoidTyID) { // List is terminated by Void
+    const Type *Ty = getType(MethSignature);
+    if (!Ty || !Ty->isMethodType()) { 
+      cerr << "Method not meth type! ";
+      if (Ty) cerr << Ty->getName(); else cerr << MethSignature; cerr << endl; 
+      return true; 
+    }
+
+    // When the ModuleGlobalInfo section is read, we load the type of each method
+    // and the 'ModuleValues' slot that it lands in.  We then load a placeholder
+    // into its slot to reserve it.  When the method is loaded, this placeholder
+    // is replaced.
+
+    // Insert the placeholder...
+    Value *Def = new MethPHolder(Ty, 0);
+    insertValue(Def, ModuleValues);
+
+    // Figure out which entry of its typeslot it went into...
+    unsigned TypeSlot;
+    if (getTypeSlot(Def->getType(), TypeSlot)) return true;
+
+    unsigned SlotNo = ModuleValues[TypeSlot].size()-1;
+    
+    // Keep track of this information in a linked list that is emptied as 
+    // methods are loaded...
+    //
+    MethodSignatureList.push_back(make_pair((const MethodType*)Ty, SlotNo));
+    if (read_vbr(Buf, End, MethSignature)) return true;
+  }
+
+  if (align32(Buf, End)) return true;
+
+  // This is for future proofing... in the future extra fields may be added that
+  // we don't understand, so we transparently ignore them.
+  //
+  Buf = End;
+  return false;
+}
+
+bool BytecodeParser::ParseModule(const uchar *Buf, const uchar *EndBuf, 
+				Module *&C) {
+
+  unsigned Type, Size;
+  if (readBlock(Buf, EndBuf, Type, Size)) return true;
+  if (Type != BytecodeFormat::Module || Buf+Size != EndBuf)
+    return true;                               // Hrm, not a class?
+
+  MethodSignatureList.clear();                 // Just in case...
+
+  // Read into instance variables...
+  if (read_vbr(Buf, EndBuf, FirstDerivedTyID)) return true;
+  if (align32(Buf, EndBuf)) return true;
+
+  C = new Module();
+
+  while (Buf < EndBuf) {
+    const uchar *OldBuf = Buf;
+    if (readBlock(Buf, EndBuf, Type, Size)) { delete C; return true; }
+    switch (Type) {
+    case BytecodeFormat::ModuleGlobalInfo:
+      if (ParseModuleGlobalInfo(Buf, Buf+Size, C)) {
+	cerr << "Error reading class global info section!\n";
+	delete C; return true;
+      }
+      break;
+
+    case BytecodeFormat::ConstantPool:
+      if (ParseConstantPool(Buf, Buf+Size, C->getConstantPool(), ModuleValues)) {
+	cerr << "Error reading class constant pool!\n";
+	delete C; return true;
+      }
+      break;
+
+    case BytecodeFormat::Method: {
+      if (ParseMethod(Buf, Buf+Size, C)) {
+	delete C; return true;               // Error parsing method
+      }
+      break;
+    }
+
+    case BytecodeFormat::SymbolTable:
+      if (ParseSymbolTable(Buf, Buf+Size)) {
+	cerr << "Error reading class symbol table!\n";
+	delete C; return true;
+      }
+      break;
+
+    default:
+      cerr << "Unknown class block: " << Type << endl;
+      Buf += Size;
+      if (OldBuf > Buf) return true; // Wrap around!
+      break;
+    }
+    if (align32(Buf, EndBuf)) { delete C; return true; }
+  }
+
+  if (!MethodSignatureList.empty())      // Expected more methods!
+    return true;
+  return false;
+}
+
+Module *BytecodeParser::ParseBytecode(const uchar *Buf, const uchar *EndBuf) {
+  LateResolveValues.clear();
+  unsigned Sig;
+  // Read and check signature...
+  if (read(Buf, EndBuf, Sig) ||
+      Sig != ('l' | ('l' << 8) | ('v' << 16) | 'm' << 24))
+    return 0;                                         // Invalid signature!
+
+  Module *Result;
+  if (ParseModule(Buf, EndBuf, Result)) return 0;
+  return Result;
+}
+
+
+Module *ParseBytecodeBuffer(const uchar *Buffer, unsigned Length) {
+  BytecodeParser Parser;
+  return Parser.ParseBytecode(Buffer, Buffer+Length);
+}
+
+// Parse and return a class file...
+//
+Module *ParseBytecodeFile(const string &Filename) {
+  struct stat StatBuf;
+  Module *Result = 0;
+
+  if (Filename != string("-")) {        // Read from a file...
+    int FD = open(Filename.data(), O_RDONLY);
+    if (FD == -1) return 0;
+
+    if (fstat(FD, &StatBuf) == -1) { close(FD); return 0; }
+
+    int Length = StatBuf.st_size;
+    if (Length == 0) { close(FD); return 0; }
+    uchar *Buffer = (uchar*)mmap(0, Length, PROT_READ, 
+				MAP_PRIVATE, FD, 0);
+    if (Buffer == (uchar*)-1) { close(FD); return 0; }
+
+    BytecodeParser Parser;
+    Result  = Parser.ParseBytecode(Buffer, Buffer+Length);
+
+    munmap((char*)Buffer, Length);
+    close(FD);
+  } else {                              // Read from stdin
+    size_t FileSize = 0;
+    int BlockSize;
+    uchar Buffer[4096], *FileData = 0;
+    while ((BlockSize = read(0, Buffer, 4))) {
+      if (BlockSize == -1) { free(FileData); return 0; }
+
+      FileData = (uchar*)realloc(FileData, FileSize+BlockSize);
+      memcpy(FileData+FileSize, Buffer, BlockSize);
+      FileSize += BlockSize;
+    }
+
+    if (FileSize == 0) { free(FileData); return 0; }
+
+#define ALIGN_PTRS 1
+#if ALIGN_PTRS
+    uchar *Buf = (uchar*)mmap(0, FileSize, PROT_READ|PROT_WRITE, 
+			      MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+    assert((Buf != (uchar*)-1) && "mmap returned error!");
+    free(FileData);
+    memcpy(Buf, FileData, FileSize);
+#else
+    uchar *Buf = FileData;
+#endif
+
+    BytecodeParser Parser;
+    Result = Parser.ParseBytecode(Buf, Buf+FileSize);
+
+#if ALIGN_PTRS
+    munmap((char*)Buf, FileSize);   // Free mmap'd data area
+#else
+    free(FileData);          // Free realloc'd block of memory
+#endif
+  }
+
+  return Result;
+}
