Index: include/llvm/LinkAllPasses.h
===================================================================
--- include/llvm/LinkAllPasses.h	(revision 135516)
+++ include/llvm/LinkAllPasses.h	(working copy)
@@ -30,6 +30,13 @@
 #include "llvm/Function.h"
 #include "llvm/Transforms/Instrumentation.h"
 #include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/MemSafety/AllocatorInfo.h"
+#include "llvm/Transforms/MemSafety/DebugInstrumentation.h"
+#include "llvm/Transforms/MemSafety/GEPChecks.h"
+#include "llvm/Transforms/MemSafety/LoadStoreChecks.h"
+#include "llvm/Transforms/MemSafety/RegisterBounds.h"
+#include "llvm/Transforms/MemSafety/RegisterRuntimeInitializer.h"
+#include "llvm/Transforms/MemSafety/OptimizeChecks.h"
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
 #include <cstdlib>
@@ -156,6 +163,19 @@
       (void)new llvm::IntervalPartition();
       (void)new llvm::FindUsedTypes();
       (void)new llvm::ScalarEvolution();
+
+      (void)new llvm::AllocatorInfoPass();
+      (void)new llvm::InsertLSChecks();
+      (void)new llvm::InsertGEPChecks();
+      (void)new llvm::RegisterGlobalVariables();
+      (void)new llvm::RegisterMainArgs();
+      (void)new llvm::RegisterCustomizedAllocation();
+      (void)new llvm::RegisterFunctionByvalArguments ();
+      (void)new llvm::RegisterStackObjPass ();
+      (void)new llvm::RegisterRuntimeInitializer();
+      (void)new llvm::DebugInstrument();
+      (void)new llvm::ExactCheckOpt();
+
       ((llvm::Function*)0)->viewCFGOnly();
       llvm::RGPassManager RGM(0);
       ((llvm::RegionPass*)0)->runOnRegion((llvm::Region*)0, RGM);
Index: include/llvm/Transforms/MemSafety/CheckInfo.h
===================================================================
--- include/llvm/Transforms/MemSafety/CheckInfo.h	(revision 0)
+++ include/llvm/Transforms/MemSafety/CheckInfo.h	(revision 0)
@@ -0,0 +1,63 @@
+//===- CheckInfo.h - Information about SAFECode run-time checks --*- C++ -*---//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements structures containing data about the various run-time
+// checks that SAFECode inserts into code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _SC_CHECKINFO_H_
+#define _SC_CHECKINFO_H_
+
+#include "llvm/Support/CallSite.h"
+#include "llvm/Instructions.h"
+
+using namespace llvm;
+
+namespace {
+
+//
+// Structure: CheckInfo
+//
+// Description:
+//  This structure describes a run-time check.
+//
+struct CheckInfo {
+  // The name of the function implementing the run-time check
+  const char * name;
+
+  // The argument of the checked pointer.
+  unsigned char argno;
+
+  // A boolean indicating whether it is a memory check or a bounds check
+  bool isMemcheck;
+
+  Value * getCheckedPointer (CallInst * CI) const {
+    CallSite CS(CI);
+    return CS.getArgument (argno);
+  }
+};
+}
+
+//
+// Create a table describing all of the SAFECode run-time checks.
+//
+static const unsigned numChecks = 8;
+static const struct CheckInfo RuntimeChecks[numChecks] = {
+  {"lscheck",        1, true},
+  {"lscheckui",      1, true},
+  {"lscheckalign",   1, true},
+  {"lscheckuialign", 1, true},
+  {"boundscheck",    2, false},
+  {"boundscheckui",  2, false},
+  {"exactcheck2",    1, false},
+  {"funccheck",      1, true}
+};
+
+#endif
Index: include/llvm/Transforms/MemSafety/DebugInstrumentation.h
===================================================================
--- include/llvm/Transforms/MemSafety/DebugInstrumentation.h	(revision 0)
+++ include/llvm/Transforms/MemSafety/DebugInstrumentation.h	(revision 0)
@@ -0,0 +1,88 @@
+//===- DebugInstrumentation.h - Adds debug information to run-time checks ----//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This pass modifies calls to the pool allocator and SAFECode run-times to
+// track source level debugging information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DEBUG_INSTRUMENTATION_H
+#define DEBUG_INSTRUMENTATION_H
+
+#include "llvm/Instructions.h"
+#include "llvm/Pass.h"
+#include "llvm/Type.h"
+#include "llvm/Value.h"
+
+#include <map>
+#include <string>
+#include <utility>
+
+namespace llvm {
+
+class GetSourceInfo {
+  protected:
+    // The ID for debug metadata
+    unsigned dbgKind;
+
+  public:
+    GetSourceInfo (unsigned dbgKindID) : dbgKind(dbgKindID) {}
+    virtual std::pair<Value *, Value *> operator() (CallInst * I) = 0;
+    virtual ~GetSourceInfo();
+};
+
+class LocationSourceInfo : public GetSourceInfo {
+  protected:
+    // Cache of file names which already have a global variable for them
+    std::map<std::string, Value *> SourceFileMap;
+
+  public:
+    LocationSourceInfo (unsigned dbgKindID) : GetSourceInfo (dbgKindID) {}
+    virtual std::pair<Value *, Value *> operator() (CallInst * I);
+};
+
+class VariableSourceInfo : public GetSourceInfo {
+  protected:
+    // Cache of file names which already have a global variable for them
+    std::map<std::string, Value *> SourceFileMap;
+
+  public:
+    VariableSourceInfo (unsigned dbgKindID) : GetSourceInfo (dbgKindID) {}
+    virtual std::pair<Value *, Value *> operator() (CallInst * I);
+};
+
+struct DebugInstrument : public ModulePass {
+  public:
+    static char ID;
+
+    virtual bool runOnModule(Module &M);
+    DebugInstrument () : ModulePass (ID) {
+      return;
+    }
+
+    const char *getPassName() const {
+      return "SAFECode Debug Instrumentation Pass";
+    }
+
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.setPreservesCFG();
+      AU.setPreservesAll();
+    };
+
+  private:
+    // LLVM type for void pointers (void *)
+    Type * VoidPtrTy;
+
+    // Private methods
+    void transformFunction (Function * F, GetSourceInfo & SI);
+};
+
+}
+
+#endif
Index: include/llvm/Transforms/MemSafety/GEPChecks.h
===================================================================
--- include/llvm/Transforms/MemSafety/GEPChecks.h	(revision 0)
+++ include/llvm/Transforms/MemSafety/GEPChecks.h	(revision 0)
@@ -0,0 +1,65 @@
+//===- GEPChecks.h - Insert run-time checks for GEPs -------------------------//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements several passes that insert run-time checks to enforce
+// SAFECode's memory safety guarantees as well as several other passes that
+// help to optimize the instrumentation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _SAFECODE_GEP_CHECKS_H_
+#define _SAFECODE_GEP_CHECKS_H_
+
+#include "llvm/Analysis/Dominators.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Instructions.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/InstVisitor.h"
+#include "llvm/Target/TargetData.h"
+
+namespace llvm {
+
+//
+// Pass: InsertGEPChecks
+//
+// Description:
+//  This pass inserts checks on GEP instructions.
+//
+struct InsertGEPChecks : public FunctionPass, InstVisitor<InsertGEPChecks> {
+  public:
+    static char ID;
+    InsertGEPChecks () : FunctionPass (ID) { }
+    const char *getPassName() const { return "Insert GEP Checks"; }
+    virtual bool  doInitialization (Module & M);
+    virtual bool runOnFunction(Function &F);
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      // Required passes
+      AU.addRequired<TargetData>();
+
+      // Preserved passes
+      AU.setPreservesCFG();
+    };
+
+    // Visitor methods
+    void visitGetElementPtrInst (GetElementPtrInst & GEP);
+
+  protected:
+    // Pointers to required passes
+    TargetData * TD;
+#if 0
+    ArrayBoundsCheckGroup * abcPass;
+#endif
+
+    // Pointer to GEP run-time check function
+    Function * PoolCheckArrayUI;
+};
+
+}
+#endif
Index: include/llvm/Transforms/MemSafety/AllocatorInfo.h
===================================================================
--- include/llvm/Transforms/MemSafety/AllocatorInfo.h	(revision 0)
+++ include/llvm/Transforms/MemSafety/AllocatorInfo.h	(revision 0)
@@ -0,0 +1,241 @@
+//===- AllocatorInfo.h ------------------------------------------*- C++ -*----//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// Define the abstraction of a pair of allocator / deallocator, including:
+//
+//   * The size of the object being allocated. 
+//   * Whether the size may be a constant, which can be used for exactcheck
+// optimization.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SAFECODE_SUPPORT_ALLOCATORINFO_H
+#define SAFECODE_SUPPORT_ALLOCATORINFO_H
+
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Value.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Transforms/MemSafety/Utility.h"
+
+#include <stdint.h>
+#include <string>
+
+namespace llvm {
+
+/// AllocatorInfo - define the abstraction of a pair of allocator / deallocator.
+class AllocatorInfo {
+  public:
+    AllocatorInfo(const std::string & allocCallName, 
+                  const std::string & freeCallName) : 
+    allocCallName(allocCallName), freeCallName(freeCallName) {}
+
+    virtual ~AllocatorInfo();
+    /// Test whether the size of a particular allocation site may be a constant.
+    /// This is used to determined whether SAFECode can perform an exactcheck
+    /// optimization on the particular allocation site.
+    /// 
+    /// For simple allocators such as malloc() / poolalloc(), that is always
+    /// true. However, allocators such as kmem_cache_alloc() put the size of
+    /// allocation inside a struct, which needs extra instructions to get the
+    /// size. We don't want to get into this complexity right now, even running
+    /// ADCE right after exactcheck optimization might fix the problem.
+    ///
+    virtual bool isAllocSizeMayConstant(Value * AllocSite) const {
+      return true;
+    }
+
+    /// Return the size of the object being allocated
+    /// Assume the caller knows it is an allocation for this allocator
+    /// Return NULL when something is wrong
+    virtual Value * getAllocSize(Value * AllocSite) const = 0;
+
+    /// Return the size of the object being allocated; insert code into the
+    /// program to compute the size if necessary
+    virtual Value * getOrCreateAllocSize (Value * AllocSite) const = 0;
+
+    /// Return the pointer being freed
+    /// Return NULL when something is wrong
+    virtual Value * getFreedPointer(Value * FreeSite) const = 0;
+
+    /// Return the function name of the allocator, say "malloc".
+    const std::string & getAllocCallName() const { return allocCallName; }
+
+    /// Return the function name of the deallocator, say "free".
+    const std::string & getFreeCallName() const { return freeCallName; }
+
+  protected:
+    std::string allocCallName;
+    std::string freeCallName;
+};
+
+/// SimpleAllocatorInfo - define the abstraction of simple allcators /
+/// deallocators such as malloc / free
+class SimpleAllocatorInfo : public AllocatorInfo {
+  public:
+    SimpleAllocatorInfo(const std::string & allocCallName, 
+                        const std::string & freeCallName,
+                        uint32_t allocSizeOperand,
+                        uint32_t freePtrOperand) :
+      AllocatorInfo(allocCallName, freeCallName),
+      allocSizeOperand(allocSizeOperand), freePtrOperand(freePtrOperand) {}
+    virtual Value * getAllocSize(Value * AllocSite) const;
+    virtual Value * getOrCreateAllocSize(Value * AllocSite) const;
+    virtual Value * getFreedPointer(Value * FreeSite) const;
+
+  protected:
+    uint32_t allocSizeOperand;
+    uint32_t freePtrOperand;
+};
+
+/// ReAllocatorInfo - define the abstraction of simple reallcators /
+/// deallocators such as realloc / free
+class ReAllocatorInfo : public SimpleAllocatorInfo {
+  public:
+    ReAllocatorInfo(const std::string & allocCallName, 
+                    const std::string & freeCallName,
+                    uint32_t allocSizeOperand,
+                    uint32_t allocPtrOperand,
+                    uint32_t freePtrOperand) :
+      SimpleAllocatorInfo(allocCallName,
+                          freeCallName,
+                          allocSizeOperand,
+                          freePtrOperand),
+      allocPtrOperand(allocPtrOperand) {}
+    virtual Value * getAllocedPointer (Value * AllocSite) const;
+
+  protected:
+    uint32_t allocPtrOperand;
+};
+
+/// ArrayAllocatorInfo - define the abstraction of array allcators /
+/// deallocators such as calloc / free
+class ArrayAllocatorInfo : public SimpleAllocatorInfo {
+  protected:
+    // The index of the operand used for the number of elements to allocate
+    uint32_t allocNumOperand;
+
+  public:
+    ArrayAllocatorInfo(const std::string & allocCallName, 
+                       const std::string & freeCallName,
+                       uint32_t allocSizeOperand,
+                       uint32_t allocNumOperand,
+                       uint32_t freePtrOperand) :
+      SimpleAllocatorInfo (allocCallName, freeCallName, allocSizeOperand, freePtrOperand), allocNumOperand (allocNumOperand) {}
+    virtual Value * getAllocSize(Value * AllocSite) const {
+      return 0;
+    }
+    virtual Value * getOrCreateAllocSize(Value * AllocSite) const;
+};
+
+/// StringAllocatorInfo - define the abstraction of string allocator functions
+class StringAllocatorInfo : public SimpleAllocatorInfo {
+  public:
+    StringAllocatorInfo(const std::string & allocCallName, 
+                        const std::string & freeCallName,
+                        uint32_t freePtrOperand) :
+      SimpleAllocatorInfo (allocCallName, freeCallName, 0, freePtrOperand) {}
+    virtual Value * getAllocSize(Value * AllocSite) const {
+      return 0;
+    }
+    virtual Value * getOrCreateAllocSize(Value * AllocSite) const;
+};
+
+//
+// Pass: AllocatorInfoPass
+//
+// Description:
+//  This is a pass that can be queried to find information about various
+//  allocation functions.
+//
+class AllocatorInfoPass : public ImmutablePass {
+  public:
+    typedef std::vector<AllocatorInfo *> AllocatorInfoListTy;
+    typedef AllocatorInfoListTy::iterator alloc_iterator;
+    typedef std::vector<ReAllocatorInfo *> ReAllocatorInfoListTy;
+    typedef ReAllocatorInfoListTy::iterator realloc_iterator;
+
+  protected:
+    // List of allocator/deallocator functions
+    AllocatorInfoListTy allocators;
+
+    // List of reallocator functions
+    ReAllocatorInfoListTy reallocators;
+
+  public:
+    // Pass members and methods
+    static char ID;
+    AllocatorInfoPass() : ImmutablePass(ID) {
+      //
+      // Register the standard C library allocators.
+      //
+      static SimpleAllocatorInfo CPP1Allocator   ("_Znwm", "_ZdlPv", 1, 1);
+      static SimpleAllocatorInfo CPP2Allocator   ("_Znam", "_ZdaPv", 1, 1);
+      static SimpleAllocatorInfo CPP3Allocator   ("_Znwj", "", 1, 1);
+      static SimpleAllocatorInfo CPP4Allocator   ("_Znaj", "", 1, 1);
+      static SimpleAllocatorInfo MallocAllocator ("malloc", "free", 1, 1);
+      static ArrayAllocatorInfo  CallocAllocator ("calloc", "", 1, 2, 1);
+      static ReAllocatorInfo     ReAllocator     ("realloc", "", 2, 1, 1);
+      static StringAllocatorInfo StrdupAllocator ("strdup", "", 1);
+
+      // Add the standard C allocators
+      addAllocator   (&MallocAllocator);
+      addAllocator   (&CallocAllocator);
+      addReAllocator (&ReAllocator);
+
+      // Add the C++ allocators
+      addAllocator   (&CPP1Allocator);
+      addAllocator   (&CPP2Allocator);
+      addAllocator   (&CPP3Allocator);
+      addAllocator   (&CPP4Allocator);
+
+      // Add the string allocator functions
+      addAllocator   (&StrdupAllocator);
+      return;
+    }
+
+    virtual bool runOnModule (Module & M) {
+      //
+      // Ensure that a prototype for strlen() exists.
+      //
+      TargetData & TD = getAnalysis<TargetData>();
+      M.getOrInsertFunction ("strlen",
+                             TD.getIntPtrType(M.getContext()),
+                             getVoidPtrType(M.getContext()),
+                             NULL);
+      return true;
+    }
+
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.addRequired<TargetData>();
+      AU.setPreservesAll();
+      return;
+    }
+
+    // Iterator methods
+    alloc_iterator alloc_begin() { return allocators.begin(); }
+    alloc_iterator alloc_end() { return allocators.end(); }
+    realloc_iterator realloc_begin() { return reallocators.begin(); }
+    realloc_iterator realloc_end() { return reallocators.end(); }
+
+    // Methods to add allocators
+    void addAllocator (AllocatorInfo * Allocator) {
+      allocators.push_back (Allocator);
+    }
+
+    void addReAllocator (ReAllocatorInfo * Allocator) {
+      reallocators.push_back (Allocator);
+    }
+
+    Value * getObjectSize(Value * V);
+};
+
+}
+
+#endif
Index: include/llvm/Transforms/MemSafety/RegisterRuntimeInitializer.h
===================================================================
--- include/llvm/Transforms/MemSafety/RegisterRuntimeInitializer.h	(revision 0)
+++ include/llvm/Transforms/MemSafety/RegisterRuntimeInitializer.h	(revision 0)
@@ -0,0 +1,41 @@
+//===- include/InsertChecks/RegisterRuntimeInitializer.h --------*- C++ -*----//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// Pass to register runtime initialization calls into user-space programs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _REGISTER_RUNTIME_INITIALIZER_H_
+#define _REGISTER_RUNTIME_INITIALIZER_H_
+
+#include "llvm/Pass.h"
+#include "llvm/Module.h"
+#include "llvm/Target/TargetData.h"
+
+namespace llvm {
+
+/// Base class of all passes which register variables into pools.
+class RegisterRuntimeInitializer : public llvm::ModulePass {
+public:
+  static char ID;
+  RegisterRuntimeInitializer() : llvm::ModulePass(ID) {}
+  virtual bool runOnModule(llvm::Module & M);
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
+    AU.setPreservesAll();
+  }
+private:
+  /// Construct the initializer
+  void constructInitializer(llvm::Module & M);
+  /// Insert the initializer into llvm.global_ctors
+  void insertInitializerIntoGlobalCtorList(llvm::Module & M);
+};
+
+}
+
+#endif
Index: include/llvm/Transforms/MemSafety/LoadStoreChecks.h
===================================================================
--- include/llvm/Transforms/MemSafety/LoadStoreChecks.h	(revision 0)
+++ include/llvm/Transforms/MemSafety/LoadStoreChecks.h	(revision 0)
@@ -0,0 +1,52 @@
+//===- InsertChecks.h - Insert run-time checks for SAFECode ------------------//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements several passes that insert run-time checks to enforce
+// SAFECode's memory safety guarantees as well as several other passes that
+// help to optimize the instrumentation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _SAFECODE_LOADSTORECHECKS_H_
+#define _SAFECODE_LOADSTORECHECKS_H_
+
+#include "llvm/Pass.h"
+#include "llvm/Support/InstVisitor.h"
+
+namespace llvm {
+
+//
+// Pass: InsertLSChecks
+//
+// Description:
+//  This pass inserts checks on load and store instructions.
+//
+struct InsertLSChecks : public FunctionPass, InstVisitor<InsertLSChecks> {
+  public:
+    static char ID;
+    InsertLSChecks () : FunctionPass (ID) { }
+    const char *getPassName() const { return "Insert Load/Store Checks"; }
+    virtual bool  doInitialization (Module & M);
+    virtual bool runOnFunction(Function & F);
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      // Preserved passes
+      AU.setPreservesCFG();
+    };
+
+    // Visitor methods
+    void visitLoadInst  (LoadInst  & LI);
+    void visitStoreInst (StoreInst & SI);
+
+  protected:
+    // Pointer to load/store run-time check function
+    Function * PoolCheckUI;
+};
+
+}
+#endif
Index: include/llvm/Transforms/MemSafety/RegisterBounds.h
===================================================================
--- include/llvm/Transforms/MemSafety/RegisterBounds.h	(revision 0)
+++ include/llvm/Transforms/MemSafety/RegisterBounds.h	(revision 0)
@@ -0,0 +1,185 @@
+//===- InsertChecks/RegisterBounds.h ----------------------------*- C++ -*----//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// Various passes to register the bound information of variables into the pools
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _REGISTER_BOUNDS_H_
+#define _REGISTER_BOUNDS_H_
+
+#include "llvm/Analysis/DominanceFrontier.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Instructions.h"
+#include "llvm/Pass.h"
+#include "llvm/Module.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Transforms/MemSafety/AllocatorInfo.h"
+
+namespace llvm {
+
+/// Base class of all passes which register variables into pools.
+class RegisterVariables : public llvm::ModulePass {
+public:
+  RegisterVariables(char & id) : llvm::ModulePass(id) {}
+  virtual ~RegisterVariables();
+  virtual bool runOnModule(llvm::Module & M) = 0;
+protected:
+  //
+  // Method: init()
+  //
+  // Description:
+  //  This method performs some initialization that is common to all subclasses
+  //  of this pass.
+  //
+  void init(Module & M, std::string registerName);
+
+  /// Helper function to register the bound information of a variable into a
+  /// particular pool.
+  void RegisterVariableIntoPool(llvm::Value * PH, llvm::Value * val, llvm::Value * AllocSize, llvm::Instruction * InsertBefore);
+
+  /// Helper function to create the body of sc.register_globals /
+  /// sc.register_main. It inserts an empty basicblock and a ret void
+  /// instruction into the function.
+  ///
+  /// Return the last instruction of the function body.
+  llvm::Instruction * CreateRegistrationFunction(llvm::Function * F);
+
+  Function * PoolRegisterFunc;
+
+};
+
+/// Register the bound information of global variables.
+/// All registeration are placed at sc.register_globals
+class RegisterGlobalVariables : public RegisterVariables {
+public:
+  static char ID;
+  RegisterGlobalVariables() : RegisterVariables(ID) {}
+  const char * getPassName() const 
+  { return "Register Global Variables into Pools"; }
+
+  virtual bool runOnModule(llvm::Module & M);
+
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
+    AU.addRequired<llvm::TargetData>();
+    AU.setPreservesCFG();
+  }
+
+
+private:
+  // Other passes which we query
+  TargetData * TD;
+
+  // Private methods
+  void registerGV(GlobalVariable * GV, Instruction * InsertBefore);
+};
+
+/// Register the bound information of argv[] in main().
+/// All registeration are placed at sc.register_main_args
+class RegisterMainArgs : public RegisterVariables {
+public:
+  static char ID;
+  const char * getPassName() const { return "Register argv[] into Pools";}
+  RegisterMainArgs() : RegisterVariables(ID) {}
+  virtual bool runOnModule(llvm::Module & M);
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
+    AU.setPreservesCFG();
+  }
+};
+
+/// Register the bound information of custom allocators
+/// such as kmem_cache_alloc.
+///
+/// FIXME: Haohui
+/// Ideally, the pass should be organized as a FunctionPass. It should ask other
+/// analysis passes for all allocation sites, and register them.
+/// Now I hard-coded the allocation inside the pass since it is only used by SVA
+/// kernel, and DSA does not have the functionality to point out all allocation
+/// site yet.
+///
+/// Now the pass scan through all uses of customized allocators and add
+/// registration right after them.
+
+class AllocatorInfo;
+
+class RegisterCustomizedAllocation : public RegisterVariables {
+public:
+  static char ID;
+  const char * getPassName() const 
+  { return "Register customized allocations into Pools";}
+  RegisterCustomizedAllocation() : RegisterVariables(ID) {}
+  virtual bool runOnModule(llvm::Module & M);
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
+    AU.addRequired<TargetData>();
+    AU.addRequired<AllocatorInfoPass>();
+    AU.setPreservesCFG();
+  }
+
+private:
+  Function * PoolReregisterFunc;
+  Function * PoolUnregisterFunc;
+  void registerAllocationSite(llvm::CallInst * AllocSite, AllocatorInfo * info);
+  void registerReallocationSite(llvm::CallInst * AllocSite, ReAllocatorInfo * info);
+  void registerFreeSite(llvm::CallInst * FreeSite, AllocatorInfo * info);
+  void proceedAllocator(llvm::Module * M, AllocatorInfo * info);
+  void proceedReallocator(llvm::Module * M, ReAllocatorInfo * info);
+};
+
+// Pass to register byval arguments
+class RegisterFunctionByvalArguments : public RegisterVariables {
+public:
+  static char ID;
+  const char * getPassName() const { return "Register byval arguments of functions";}
+  RegisterFunctionByvalArguments() : RegisterVariables(ID) {}
+  virtual bool runOnModule(llvm::Module & M);
+  virtual bool runOnFunction(llvm::Function & F);
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
+    AU.addRequired<llvm::TargetData>();
+    AU.setPreservesCFG();
+  }
+private:
+  TargetData * TD;
+  Function * StackFree;
+};
+
+struct RegisterStackObjPass : public FunctionPass {
+  public:
+    static char ID;
+    RegisterStackObjPass() : FunctionPass(ID) {};
+    virtual ~RegisterStackObjPass() {};
+    virtual bool runOnFunction(Function &F);
+    virtual const char * getPassName() const {
+      return "Register stack variables into pool";
+    }
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.addRequired<TargetData>();
+      AU.addRequired<LoopInfo>();
+      AU.addRequired<DominatorTree>();
+      AU.addRequired<DominanceFrontier>();
+    };
+
+  private:
+    // References to other LLVM passes
+    TargetData * TD;
+    LoopInfo * LI;
+    DominatorTree * DT;
+    DominanceFrontier * DF;
+
+    // The pool registration function
+    Constant *PoolRegister;
+
+    CallInst * registerAllocaInst(AllocaInst *AI);
+    void insertPoolFrees (const std::vector<CallInst *> & PoolRegisters,
+                          const std::vector<Instruction *> & ExitPoints,
+                          LLVMContext * Context);
+};
+
+}
+
+#endif
Index: include/llvm/Transforms/MemSafety/OptimizeChecks.h
===================================================================
--- include/llvm/Transforms/MemSafety/OptimizeChecks.h	(revision 0)
+++ include/llvm/Transforms/MemSafety/OptimizeChecks.h	(revision 0)
@@ -0,0 +1,61 @@
+//===- OptimizeChecks.cpp - Optimize SAFECode Run-time Checks -----*- C++ -*--//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This pass optimizes some of the SAFECode run-time checks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SAFECODE_OPTIMIZECHECKS_H
+#define SAFECODE_OPTIMIZECHECKS_H
+
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/Analysis/Dominators.h"
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/MemSafety/CheckInfo.h"
+#include "llvm/Transforms/MemSafety/AllocatorInfo.h"
+
+namespace llvm {
+
+//
+// Pass: ExactCheckOpt
+//
+// Description:
+//  This pass tries to lower bounds checks and load/store checks to exact
+//  checks, that is checks whose bounds information can be determined easily,
+//  say, allocations inside a function or global variables. Therefore SAFECode
+//  does not need to register stuffs in the meta-data.
+//
+struct ExactCheckOpt : public ModulePass {
+ public:
+  static char ID;
+ ExactCheckOpt() : ModulePass(ID) {}
+  virtual bool runOnModule (Module & M);
+  const char *getPassName() const {
+    return "Exact check optimization";
+  }
+  
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+    // We need to know about SAFECode intrinsics
+    AU.addRequired<AllocatorInfoPass>();
+    AU.setPreservesCFG();
+  }
+
+ private:
+    // References to required analysis passes
+    Function *ExactCheck2;
+    bool visitCheckingIntrinsic(CallInst * CI, const struct CheckInfo & Info);
+    void rewriteToExactCheck(CallInst * CI, Value * BasePointer, 
+                             Value * ResultPointer, Value * Bounds);
+    std::vector<CallInst*> checkingIntrinsicsToBeRemoved;
+};
+
+}
+
+#endif
Index: include/llvm/Transforms/MemSafety/RewriteOOB.h
===================================================================
--- include/llvm/Transforms/MemSafety/RewriteOOB.h	(revision 0)
+++ include/llvm/Transforms/MemSafety/RewriteOOB.h	(revision 0)
@@ -0,0 +1,53 @@
+//===- RewriteOOB.cpp - Rewrite Out of Bounds Pointers -------------------- --//
+// 
+//                          The SAFECode Compiler 
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This pass performs necessary transformations to ensure that Out of Bound
+// pointer rewrites work correctly.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef REWRITEOOB_H
+#define REWRITEOOB_H
+
+#include "llvm/Analysis/Dominators.h"
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/MemSafety/CheckInfo.h"
+
+namespace llvm {
+
+//
+// Pass: RewriteOOB
+//
+// Description:
+//  This pass modifies a program so that it uses Out of Bounds pointer
+//  rewriting.  This involves modifying all uses of a checked pointer to use
+//  the return value of the run-time check.
+//
+class RewriteOOB : public ModulePass {
+  private:
+    // Private methods
+    bool processFunction (Module & M, const struct CheckInfo & Check);
+    bool addGetActualValues (Module & M);
+    void addGetActualValue (Instruction *SCI, unsigned operand);
+
+  public:
+    static char ID;
+    RewriteOOB() : ModulePass(ID) {}
+    const char *getPassName() const { return "Rewrite OOB Pass"; }
+    virtual bool runOnModule (Module & M);
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      // We require Dominator information
+      AU.addRequired<DominatorTree>();
+    }
+};
+
+}
+
+#endif
Index: include/llvm/Transforms/MemSafety/Utility.h
===================================================================
--- include/llvm/Transforms/MemSafety/Utility.h	(revision 0)
+++ include/llvm/Transforms/MemSafety/Utility.h	(revision 0)
@@ -0,0 +1,470 @@
+//===- SCUtils.h - Utility Functions for SAFECode ----------------------------//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements several utility functions used by SAFECode.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _SCUTILS_H_
+#define _SCUTILS_H_
+
+#include "llvm/BasicBlock.h"
+#include "llvm/Constants.h"
+#include "llvm/Instructions.h"
+#include "llvm/Function.h"
+#include "llvm/Module.h"
+
+#include <vector>
+#include <set>
+#include <string>
+
+namespace llvm {
+//
+// Function: isCheckingCall()
+//
+// Description:
+//  Determine whether a function is a checking routine inserted by SafeCode.
+//
+// FIXME: currently the function stays in CodeDuplication.cpp, it
+// should be a separate cpp file.
+bool isCheckingCall(const std::string & functionName);
+
+//
+// Function: getVoidPtrType()
+//
+// Description:
+//  Return a pointer to the LLVM type for a void pointer.
+//
+// Return value:
+//  A pointer to an LLVM type for the void pointer.
+//
+// Notes:
+//  Many, many passes create an LLVM void pointer type, and the code for it
+//  takes up most of the 80 columns available in a line.  This function should
+//  be easily inlined by the compiler and ease readability of the code (as well
+//  as centralize changes when LLVM's Type API is changed).
+//
+static inline
+PointerType * getVoidPtrType(Module & M) {
+  Type * Int8Type  = IntegerType::getInt8Ty (M.getContext());
+  return PointerType::getUnqual(Int8Type);
+}
+
+static inline
+PointerType * getVoidPtrType(LLVMContext & Context) {
+  Type * Int8Type  = IntegerType::getInt8Ty (Context);
+  return PointerType::getUnqual(Int8Type);
+}
+
+//
+// Function: castTo()
+//
+// Description:
+//  Given an LLVM value, insert a cast instruction to make it a given type.
+//
+static inline Value *
+castTo (Value * V, Type * Ty, Twine Name, Instruction * InsertPt) {
+  //
+  // Don't bother creating a cast if it's already the correct type.
+  //
+  assert (V && "castTo: trying to cast a NULL Value!\n");
+  if (V->getType() == Ty)
+    return V;
+
+  //
+  // If we're casting from one integer type to a smaller integer type, then
+  // use a truncate instruction.
+  //
+  IntegerType * newType = dyn_cast<IntegerType>(Ty);
+  IntegerType * oldType = dyn_cast<IntegerType>(V->getType());
+  if (newType && oldType) {
+    if (newType->getBitWidth() < oldType->getBitWidth()) {
+      return CastInst::CreateTruncOrBitCast (V, Ty, Name, InsertPt);
+    }
+  }
+
+  //
+  // If it's a constant, just create a constant expression.
+  //
+  if (Constant * C = dyn_cast<Constant>(V)) {
+    Constant * CE = ConstantExpr::getZExtOrBitCast (C, Ty);
+    return CE;
+  }
+
+  //
+  // Otherwise, insert a cast instruction.
+  //
+  return CastInst::CreateZExtOrBitCast (V, Ty, Name, InsertPt);
+}
+
+static inline Instruction *
+castTo (Instruction * I, Type * Ty, Twine Name, Instruction * InsertPt) {
+  //
+  // Don't bother creating a cast if it's already the correct type.
+  //
+  assert (I && "castTo: trying to cast a NULL Instruction!\n");
+  if (I->getType() == Ty)
+    return I;
+
+  //
+  // If we're casting from one integer type to a smaller integer type, then
+  // use a truncate instruction.
+  //
+  IntegerType * newType = dyn_cast<IntegerType>(Ty);
+  IntegerType * oldType = dyn_cast<IntegerType>(I->getType());
+  if (newType && oldType) {
+    if (newType->getBitWidth() < oldType->getBitWidth()) {
+      return CastInst::CreateTruncOrBitCast (I, Ty, Name, InsertPt);
+    }
+  }
+
+  //
+  // Otherwise, insert a cast instruction.
+  //
+  return CastInst::CreateZExtOrBitCast (I, Ty, Name, InsertPt);
+}
+
+static inline Value *
+castTo (Value * V, Type * Ty, Instruction * InsertPt) {
+  return castTo (V, Ty, "casted", InsertPt);
+}
+
+//
+// Function: indexesStructsOnly()
+//
+// Description:
+//  Determines whether the given GEP expression only indexes into structures.
+//
+// Return value:
+//  true - This GEP only indexes into structures.
+//  false - This GEP indexes into one or more arrays.
+//
+static inline bool
+indexesStructsOnly (GetElementPtrInst * GEP) {
+  Type * PType = GEP->getPointerOperand()->getType();
+  Type * ElementType;
+  unsigned int index = 1;
+  std::vector<Value *> Indices;
+  unsigned int maxOperands = GEP->getNumOperands() - 1;
+
+  //
+  // Check the first index of the GEP.  If it is non-zero, then it doesn't
+  // matter what type we're indexing into; we're indexing into an array.
+  //
+  if (ConstantInt * CI = dyn_cast<ConstantInt>(GEP->getOperand(1)))
+    if (!(CI->isNullValue ()))
+      return false;
+
+  //
+  // Scan through all types except for the last.  If any of them are an array
+  // type, the GEP is indexing into an array.
+  //
+  // If the last type is an array, the GEP returns a pointer to an array.  That
+  // means the GEP itself is not indexing into the array; this is why we don't
+  // check the type of the last GEP operand.
+  //
+  for (index = 1; index < maxOperands; ++index) {
+    Indices.push_back (GEP->getOperand(index));
+    ElementType = GetElementPtrInst::getIndexedType (PType,
+                                                     Indices.begin(),
+                                                     Indices.end());
+    assert (ElementType && "ElementType is NULL!");
+    if (isa<ArrayType>(ElementType)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+//
+// Function: peelCasts()
+//
+// Description:
+//  This method peels off casts to get to the original instruction that
+//  generated the value for the given instruction.
+//
+// Inputs:
+//  PointerOperand - The value off of which we will peel the casts.
+//
+// Outputs:
+//  Chain - The set of values that are between the original value and the
+//          specified value.
+//
+// Return value:
+//  A pointer to the LLVM value that originates the specified LLVM value.
+//
+static inline Value *
+peelCasts (Value * PointerOperand, std::set<Value *> & Chain) {
+  Value * SourcePointer = PointerOperand;
+  bool done = false;
+
+  while (!done) {
+    //
+    // Trace through constant cast and GEP expressions
+    //
+    if (ConstantExpr * cExpr = dyn_cast<ConstantExpr>(SourcePointer)) {
+      if (cExpr->isCast()) {
+        if (isa<PointerType>(cExpr->getOperand(0)->getType())) {
+          Chain.insert (SourcePointer);
+          SourcePointer = cExpr->getOperand(0);
+          continue;
+        }
+      }
+
+      // We cannot handle this expression; break out of the loop
+      break;
+    }
+
+    //
+    // Trace back through cast instructions.
+    //
+    if (CastInst * CastI = dyn_cast<CastInst>(SourcePointer)) {
+      if (isa<PointerType>(CastI->getOperand(0)->getType())) {
+        Chain.insert (SourcePointer);
+        SourcePointer = CastI->getOperand(0);
+        continue;
+      }
+      break;
+    }
+
+    // We can't scan through any more instructions; give up
+    done = true;
+  }
+
+  return SourcePointer;
+}
+
+//
+// Function: destroyFunction()
+//
+// Description:
+//  This function removes all of the existing instructions from an LLVM
+//  function and changes it to be a function declaration (i.e., no body).
+//
+// Inputs:
+//  F - A pointer to the LLVM function to destroy.
+//
+// Outputs:
+//  F - The LLVM function is modified to have no instructions.
+//
+static inline void
+destroyFunction (Function * F) {
+  //
+  // Null functions have nothing to destroy.
+  //
+  if (!F) return;
+
+  // Worklist of instructions that should be removed.
+  std::vector<Instruction *> toRemove;
+
+  //
+  // Schedule all of the instructions in the function for deletion.  We use a
+  // worklist to avoid any potential iterator invalidation.
+  //
+  for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) {
+    for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
+        toRemove.push_back (&*I);
+    }
+  }
+
+  //
+  // Remove all of the remaining instructions from each basic block first.
+  //
+  for (unsigned index = 0; index < toRemove.size(); ++index) {
+    Instruction * I = toRemove[index];
+
+    //
+    // Change all the operands so that the instruction is not using anything.
+    //
+    for (unsigned i = 0; i < I->getNumOperands(); ++i) {
+      I->setOperand (i, UndefValue::get (I->getOperand(i)->getType()));
+    }
+
+    //
+    // Remove the instruction from its basic block.
+    //
+    I->removeFromParent();
+  }
+
+  //
+  // We can now deallocate all of the old instructions.
+  //
+  while (toRemove.size()) {
+    Instruction * I = toRemove.back();
+    toRemove.pop_back();
+    delete I;
+  }
+
+  //
+  // Remove all dead basic blocks.  Again, we use a worklist to avoid any
+  // potential iterator invalidation.
+  //
+  std::vector<BasicBlock *> toRemoveBB;
+  for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) {
+    toRemoveBB.push_back (&*BB);
+  }
+
+  while (toRemoveBB.size()) {
+    BasicBlock * BB = toRemoveBB.back();
+    toRemoveBB.pop_back();
+    BB->eraseFromParent();
+  }
+
+  return;
+}
+
+//
+// Function: escapesToMemory()
+//
+// Description:
+//  Do some simple analysis to see if the value could escape into memory.
+//
+// Return value:
+//  true  - The value could (but won't necessairly) escape into memory.
+//  false - The value cannot escape into memory.
+//
+static inline bool
+escapesToMemory (Value * V) {
+  // Worklist of values to process
+  std::vector<Value *> Worklist;
+  Worklist.push_back (V);
+
+  //
+  // Scan through all uses of the value and see if any of them can escape into
+  // another function or into memory.
+  //
+  while (Worklist.size()) {
+    //
+    // Get the next value off of the worklist.
+    //
+    Value * V = Worklist.back();
+    Worklist.pop_back();
+
+    //
+    // Scan through all uses of the value.
+    //
+    for (Value::use_iterator UI = V->use_begin(); UI != V->use_end(); ++UI) {
+      //
+      // We cannot handle PHI nodes because they might introduce a recurrence
+      // in the def-use chain, and we're not handling such cycles at the
+      // moment.
+      //
+      if (isa<PHINode>(*UI)) {
+        return true;
+      }
+
+      //
+      // The pointer escapes if it's stored to memory somewhere.
+      //
+      StoreInst * SI;
+      if ((SI = dyn_cast<StoreInst>(*UI)) && (SI->getOperand(0) == V)) {
+        return true;
+      }
+
+      //
+      // For a select instruction, assume that the pointer escapes.  The reason
+      // is that the exactcheck() optimization can't trace back through a
+      // select.
+      //
+      if (isa<SelectInst>(*UI)) {
+        return true;
+      }
+
+      //
+      // GEP instructions are okay but need to be added to the worklist.
+      //
+      if (isa<GetElementPtrInst>(*UI)) {
+        Worklist.push_back (*UI);
+        continue;
+      }
+
+      //
+      // Cast instructions are okay even if they lose bits.  Some of the bits
+      // will end up in the result.
+      //
+      if (isa<CastInst>(*UI)) {
+        Worklist.push_back (*UI);
+        continue;
+      }
+
+      //
+      // Cast constant expressions are okay, too.
+      //
+      if (ConstantExpr *cExpr = dyn_cast<ConstantExpr>(*UI)) {
+        if (Instruction::isCast (cExpr->getOpcode())) {
+          Worklist.push_back (*UI);
+          continue;
+        } else {
+          return true;
+        }
+      }
+
+      //
+      // Load instructions are okay.
+      //
+      if (isa<LoadInst>(*UI)) {
+        continue;
+      }
+
+      //
+      // Call instructions are okay if we understand the semantics of the
+      // called function.  Otherwise, assume they call a function that allows
+      // the pointer to escape into memory.
+      //
+      if (CallInst * CI = dyn_cast<CallInst>(*UI)) {
+        if (!(CI->getCalledFunction())) {
+          return true;
+        }
+
+        std::string FuncName = CI->getCalledFunction()->getName();
+        if ((FuncName == "sc.exactcheck2") ||
+            (FuncName == "sc.boundscheck") ||
+            (FuncName == "sc.boundscheckui")) {
+          Worklist.push_back (*UI);
+          continue;
+        } else if ((FuncName == "llvm.memcpy.i32")    || 
+                   (FuncName == "llvm.memcpy.i64")    ||
+                   (FuncName == "llvm.memset.i32")    ||
+                   (FuncName == "llvm.memset.i64")    ||
+                   (FuncName == "llvm.memmove.i32")   ||
+                   (FuncName == "llvm.memmove.i64")   ||
+                   (FuncName == "llva_memcpy")        ||
+                   (FuncName == "llva_memset")        ||
+                   (FuncName == "llva_strncpy")       ||
+                   (FuncName == "llva_invokememcpy")  ||
+                   (FuncName == "llva_invokestrncpy") ||
+                   (FuncName == "llva_invokememset")  ||
+                   (FuncName == "sc.pool_register")  ||
+                   (FuncName == "sc.pool_register_stack")  ||
+                   (FuncName == "sc.pool_register_global")  ||
+                   (FuncName == "memcmp")) {
+          continue;
+        } else {
+          return true;
+        }
+      }
+
+      //
+      // We don't know what this is.  Just assume it can escape to memory.
+      //
+      return true;
+    }
+  }
+
+  //
+  // No use causes the value to escape to memory.
+  //
+  return false;
+}
+
+}
+
+#endif
+
Index: runtime/libsc/include/DebugRuntime.h
===================================================================
--- runtime/libsc/include/DebugRuntime.h	(revision 0)
+++ runtime/libsc/include/DebugRuntime.h	(revision 0)
@@ -0,0 +1,256 @@
+//===- SAFECodeRuntime.h -- Runtime interface of SAFECode ------*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrast`ructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface of SAFECode runtime library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _SAFECODE_RUNTIME_H_
+#define _SAFECODE_RUNTIME_H_
+
+#include "BitmapAllocator.h"
+#include "SplayTree.h"
+
+#include <iosfwd>
+#include <stdint.h>
+
+namespace llvm {
+
+//
+// Enumerated Type: allocType
+//
+// Description:
+//  This enumerated type lists the different types of allocations that can be
+//  made.
+//
+enum allocType {
+  Global,   // Global object
+  Stack,    // Stack-allocated object
+  Heap      // Heap-allocated object
+};
+
+//
+// Structure: DebugMetaData
+//
+// Description:
+//  This structure contains information on the error to be reported.
+//
+// Fields:
+//  allocID    : The ID number of the allocation of the object.
+//  freeID     : The ID number of the deallocation of the object.
+//  allocPC    : The program counter at which the object was last allocated.
+//  freePC     : The program counter at which the object was last deallocated.
+//  canonAddr  : The canonical address of the memory reference.
+//  SourceFile : A string containing the source file to which the erring
+//               instruction is found.
+//  lineno     : The line number in the source file to which the erring
+//               instruction is found.
+//
+typedef struct DebugMetaData {
+  unsigned allocID;
+  unsigned freeID;
+  void * allocPC;
+  void * freePC;
+  void * canonAddr;
+
+  // Allocation type (global, stack, or heap object)
+  allocType allocationType;
+
+  // Source filename
+  const void * SourceFile;
+
+  // Source filename for deallocation
+  const void * FreeSourceFile;
+
+  // Line number
+  unsigned lineno;
+
+  // Line number for deallocation
+  unsigned Freelineno;
+
+  void print(std::ostream & OS) const;
+} DebugMetaData;
+typedef DebugMetaData * PDebugMetaData;
+
+struct DebugPoolTy : public BitmapPoolTy {
+  // Splay tree used for object registration
+  RangeSplaySet<> Objects;
+
+  // Splay tree used for out of bound objects
+  RangeSplayMap<void *> OOB;
+
+  // Splay tree used by dangling pointer runtime
+  RangeSplayMap<PDebugMetaData> DPTree;
+
+  // Cache of recently found memory objects
+  struct {
+    void * lower;
+    void * upper;
+  } objectCache[2];
+
+  unsigned char cacheIndex;
+};
+
+void * rewrite_ptr (DebugPoolTy * Pool, const void * p, const void * ObjStart,
+const void * ObjEnd, const char * SourceFile, unsigned lineno);
+void installAllocHooks (void);
+
+}
+
+// Use macros so that I won't polluate the namespace
+
+#define PPOOL llvm::DebugPoolTy*
+#define TAG unsigned
+#define SRC_INFO const char *, unsigned int
+
+extern "C" {
+  void pool_init_runtime(unsigned Dangling,
+                         unsigned RewriteOOB,
+                         unsigned Terminate);
+  void * __sc_dbg_newpool(unsigned NodeSize);
+  void __sc_dbg_pooldestroy(PPOOL);
+
+  void * __sc_dbg_poolinit(PPOOL, unsigned NodeSize, unsigned);
+  void * __sc_dbg_poolalloc(PPOOL, unsigned NumBytes);
+  void * __sc_dbg_src_poolalloc (PPOOL, unsigned Size, TAG, SRC_INFO);
+
+  void * poolargvregister (int argc, char ** argv);
+
+  void pool_register       (PPOOL, void *allocaptr, unsigned NumBytes);
+  void pool_register_debug (PPOOL, void * p, unsigned size, TAG, SRC_INFO);
+  void pool_register_stack      (PPOOL, void * p, unsigned size);
+  void pool_register_stack_debug(PPOOL, void * p, unsigned size, TAG, SRC_INFO);
+  void pool_register_global (PPOOL, void * p, unsigned size);
+  void pool_register_global_debug(PPOOL, void * p, unsigned size, TAG, SRC_INFO);
+
+  void pool_reregister (PPOOL, void * p, void * q, unsigned size);
+  void pool_reregister_debug (PPOOL, void * p, void * q, unsigned size, TAG, SRC_INFO);
+
+  void pool_unregister(PPOOL, void *allocaptr);
+  void pool_unregister_debug(PPOOL, void *allocaptr, TAG, SRC_INFO);
+  void pool_unregister_stack(PPOOL, void *allocaptr);
+  void pool_unregister_stack_debug(PPOOL, void *allocaptr, TAG, SRC_INFO);
+  void __sc_dbg_poolfree(PPOOL, void *Node);
+  void __sc_dbg_src_poolfree (PPOOL, void *, TAG, SRC_INFO);
+
+  void * __sc_dbg_poolcalloc (PPOOL, unsigned Number, unsigned NumBytes);
+  void * __sc_dbg_src_poolcalloc (PPOOL,
+                                unsigned Number, unsigned NumBytes,
+                                  TAG, SRC_INFO);
+
+  void * __sc_dbg_poolrealloc(PPOOL, void *Node, unsigned NumBytes);
+  void * __sc_dbg_poolrealloc_debug(PPOOL, void *Node, unsigned NumBytes, TAG, SRC_INFO);
+  void * __sc_dbg_poolstrdup (PPOOL, const char * Node);
+  void * __sc_dbg_poolstrdup_debug (PPOOL, const char * Node, TAG, SRC_INFO);
+  void * __sc_dbg_poolmemalign(PPOOL, unsigned Alignment, unsigned NumBytes);
+
+  void poolcheck(PPOOL, void *Node);
+  void poolcheckui(PPOOL, void *Node);
+  void poolcheck_debug (PPOOL, void * Node, TAG, SRC_INFO);
+  void poolcheckui_debug (PPOOL, void * Node, TAG, SRC_INFO);
+
+  void poolcheckalign(PPOOL, void *Node, unsigned Offset);
+  void poolcheckalign_debug (PPOOL, void *Node, unsigned Offset, TAG, SRC_INFO);
+
+  void * boundscheck   (PPOOL, void * Source, void * Dest);
+  void * boundscheckui (PPOOL, void * Source, void * Dest);
+  void * boundscheckui_debug (PPOOL, void * S, void * D, TAG, SRC_INFO);
+  void * boundscheck_debug (PPOOL, void * S, void * D, TAG, SRC_INFO);
+
+  // CStdLib
+  void * pool_memcpy(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, size_t n, const uint8_t complete);
+  void * pool_memcpy_debug(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, size_t n, const uint8_t complete, TAG, SRC_INFO);
+  void * pool_mempcpy(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, size_t n, const uint8_t complete);
+  void * pool_mempcpy_debug(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, size_t n, const uint8_t complete, TAG, SRC_INFO);
+  void * pool_memmove(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, size_t n, const uint8_t complete);
+  void * pool_memmove_debug(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, size_t n, const uint8_t complete, TAG, SRC_INFO);
+  void * pool_memset(PPOOL sPool, void *s, int c, size_t n, const uint8_t complete);
+  void * pool_memset_debug(PPOOL sPool, void *s, int c, size_t n, const uint8_t complete, TAG, SRC_INFO);
+
+  char * pool_strcpy(PPOOL dstPool, PPOOL srcPool, char *dst, const char *src, const uint8_t complete);
+  char * pool_strcpy_debug(PPOOL dstPool, PPOOL srcPool, char *dst, const char *src, const uint8_t complete, TAG, SRC_INFO);
+  char * pool_stpcpy(PPOOL dstPool, PPOOL srcPool, char *dst, const char *src, const uint8_t complete);
+  char * pool_stpcpy_debug(PPOOL dstPool, PPOOL srcPool, char *dst, const char *src, const uint8_t complete, TAG, SRC_INFO);
+  size_t pool_strlen(PPOOL stringPool, const char *string, const uint8_t complete);
+  size_t pool_strlen_debug(PPOOL stringPool, const char *string, const uint8_t complete, TAG, SRC_INFO);
+  char * pool_strncpy(PPOOL dstPool, PPOOL srcPool, char *dst, const char *src, size_t n,const uint8_t complete);
+  char * pool_strncpy_debug(PPOOL dstPool, PPOOL srcPool, char *dst, const char *src, size_t n, const uint8_t complete, TAG, SRC_INFO);
+  size_t pool_strnlen(PPOOL stringPool, const char *string, size_t maxlen,const uint8_t complete);
+  size_t pool_strnlen_debug(PPOOL stringPool, const char *string, size_t maxlen, const uint8_t complete, TAG, SRC_INFO);
+
+
+  char * pool_strchr(PPOOL sPool, const char *s, int c, const uint8_t complete);
+  char * pool_strchr_debug(PPOOL sPool, const char *s, int c, const uint8_t complete, TAG, SRC_INFO);
+  char * pool_strrchr(PPOOL sPool, const char *s, int c, const uint8_t complete);
+  char * pool_strrchr_debug(PPOOL sPool, const char *s, int c, const uint8_t complete, TAG, SRC_INFO);
+  char * pool_strstr(PPOOL s1Pool, PPOOL s2Pool, const char *s1, const char *s2, const uint8_t complete);
+  char * pool_strstr_debug(PPOOL s1Pool, PPOOL s2Pool, const char *s1, const char *s2,
+                           const uint8_t complete, TAG, SRC_INFO);
+  char * pool_strcat(PPOOL dstPool, PPOOL srcPool, char *d, const char *s, const uint8_t complete);
+  char * pool_strcat_debug(PPOOL dstPool, PPOOL srcPool, char *d, const char *s, const uint8_t complete, TAG, SRC_INFO);
+  char * pool_strncat(PPOOL dstPool, PPOOL srcPool, char *d, const char *s, size_t n, const uint8_t complete);
+  char * pool_strncat_debug(PPOOL dstPool, PPOOL srcPool, char *d, const char *s, size_t n,
+                            const uint8_t complete, TAG, SRC_INFO);
+  char * pool_strpbrk(PPOOL sPool, PPOOL aPool, const char *s, const char *a, const uint8_t complete);
+  char * pool_strpbrk_debug(PPOOL sPool, PPOOL aPool, const char *s, const char *a,
+                            const uint8_t complete, TAG, SRC_INFO);
+  
+  int    pool_strcmp(PPOOL str1Pool, PPOOL str2Pool, const char *str1, const char *str2, const uint8_t complete);
+  int    pool_strcmp_debug(PPOOL str1Pool, PPOOL str2Pool, const char *str1, const char *str2, const uint8_t complete, TAG, SRC_INFO);
+  int    pool_strncmp(PPOOL s1p,PPOOL s2p,const char *s1, const char *s2,size_t num,const uint8_t complete);
+  int    pool_strncmp_debug(PPOOL s1p,PPOOL s2p,const char *s1, const char *s2,size_t num,const uint8_t complete, TAG, SRC_INFO);
+  int    pool_strcasecmp(PPOOL str1Pool, PPOOL str2Pool, const char *str1, const char *str2, const uint8_t complete);
+  int    pool_strcasecmp_debug(PPOOL str1Pool, PPOOL str2Pool, const char *str1, const char *str2, const uint8_t complete, TAG, SRC_INFO);
+  int    pool_strncasecmp(PPOOL s1p,PPOOL s2p,const char *s1, const char *s2,size_t num,const uint8_t complete);
+  int    pool_strncasecmp_debug(PPOOL s1p,PPOOL s2p,const char *s1, const char *s2,size_t num,const uint8_t complete, TAG, SRC_INFO);
+  int    pool_memcmp(PPOOL s1p,PPOOL s2p,const void *s1, const void *s2,size_t num,const uint8_t complete);
+  int    pool_memcmp_debug(PPOOL s1p,PPOOL s2p,const void *s1, const void *s2,size_t num,const uint8_t complete, TAG, SRC_INFO);
+  int    pool_strspn(PPOOL s1p,PPOOL s2p,const char *s1, const char *s2,const uint8_t complete);
+  int    pool_strspn_debug(PPOOL s1p,PPOOL s2p,const char *s1, const char *s2,const uint8_t complete, TAG, SRC_INFO);
+  int    pool_strcspn(PPOOL s1p,PPOOL s2p,const char *s1, const char *s2,const uint8_t complete);
+  int    pool_strcspn_debug(PPOOL s1p,PPOOL s2p,const char *s1, const char *s2,const uint8_t complete, TAG, SRC_INFO);
+
+  void * pool_memccpy(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, char c, size_t n, const uint8_t complete);
+  void * pool_memccpy_debug(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, char c, size_t n, const uint8_t complete, TAG, SRC_INFO);
+  void * pool_memchr(PPOOL sPool, void *s, int c, size_t n, const uint8_t complete);
+  void * pool_memchr_debug(PPOOL sPool, void *s, int c, size_t n, const uint8_t complete, TAG, SRC_INFO);
+  int    pool_bcmp(PPOOL aPool, PPOOL bPool, const void *a, const void *b, size_t n, const uint8_t complete);
+  int    pool_bcmp_debug(PPOOL aPool, PPOOL bPool, const void *a, const void *b, size_t n, const uint8_t complete, TAG, SRC_INFO);
+  void   pool_bcopy(PPOOL aPool, PPOOL bPool, const void *a, void *b, size_t n, const uint8_t complete);
+  void   pool_bcopy_debug(PPOOL aPool, PPOOL bPool, const void *a, void *b, size_t n, const uint8_t complete, TAG, SRC_INFO);
+  void   pool_bzero(PPOOL sPool, void *s, size_t n, const uint8_t complete);
+  void   pool_bzero_debug(PPOOL sPool, void *s, size_t n, const uint8_t complete, TAG, SRC_INFO);
+  char * pool_index(PPOOL sPool, const char *s, int c, const uint8_t complete);
+  char * pool_index_debug(PPOOL sPool, const char *s, int c, const uint8_t complete, TAG, SRC_INFO);
+  char * pool_rindex(PPOOL sPool, const char *s, int c, const uint8_t complete);
+  char * pool_rindex_debug(PPOOL sPool, const char *s, int c, const uint8_t complete, TAG, SRC_INFO);
+  char * pool_strcasestr(PPOOL s1Pool, PPOOL s2Pool, const char *s1, const char *s2, const uint8_t complete);
+  char * pool_strcasestr_debug(PPOOL s1Pool, PPOOL s2Pool, const char *s1, const char *s2, const uint8_t complete, TAG, SRC_INFO);
+
+#ifdef _GNU_SOURCE
+  void * pool_mempcpy(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, size_t n, const uint8_t complete);
+#endif
+
+  // Exact checks
+  void * exactcheck2 (const char *base, const char *result, unsigned size);
+  void * exactcheck2_debug (const char *base, const char *result, unsigned size,
+                            TAG, SRC_INFO);
+
+  void __sc_dbg_funccheck (unsigned num, void *f, void *g, ...);
+  void * pchk_getActualValue (PPOOL, void * src);
+
+  // Change memory protections to detect dangling pointers
+  void * pool_shadow (void * Node, unsigned NumBytes);
+  void * pool_unshadow (void * Node);
+}
+
+#undef PPOOL
+#undef TAG
+#undef SRC_INFO
+#endif
Index: runtime/libsc/include/HashExtras.h
===================================================================
--- runtime/libsc/include/HashExtras.h	(revision 0)
+++ runtime/libsc/include/HashExtras.h	(revision 0)
@@ -0,0 +1,49 @@
+//===-- poolalloc/ADT/HashExtras.h - STL hashing for LLVM -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains some templates that are useful if you are working with the
+// STL Hashed containers.
+//
+// No library is required when using these functions.
+//
+// This header files is a modification of HashExtras.h from LLVM.  It is GNU
+// C++ specific.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POOLALLOC_ADT_HASHEXTRAS_H
+#define POOLALLOC_ADT_HASHEXTRAS_H
+
+#include <functional>
+#include <ext/hash_map>
+#include <ext/hash_set>
+#include <string>
+
+// Cannot specialize hash template from outside of the std namespace.
+namespace __gnu_cxx {
+
+// Provide a hash function for arbitrary pointers...
+template <class T> struct hash<T *> {
+  inline size_t operator()(const T *Val) const {
+    return reinterpret_cast<size_t>(Val);
+  }
+};
+
+template <> struct hash<std::string> {
+  size_t operator()(std::string const &str) const {
+    return hash<char const *>()(str.c_str());
+  }
+};
+
+}  // End namespace std
+
+// Use the namespace so that we don't need to state it explictly.
+using namespace __gnu_cxx;
+
+#endif
Index: runtime/libsc/include/Report.h
===================================================================
--- runtime/libsc/include/Report.h	(revision 0)
+++ runtime/libsc/include/Report.h	(revision 0)
@@ -0,0 +1,63 @@
+//===- Report.h -------------------------------------------------*- C++ -*-===//
+// 
+//                       The SAFECode Compiler Project
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file define the interfaces for reporting memory safety violation found
+// by SAFECode.
+// Implemenation can inherit from ViolationInfo to store more information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _REPORT_H_
+#define _REPORT_H_
+
+#include <iosfwd>
+
+namespace llvm {
+
+struct ViolationInfo {
+  enum {
+    WARN_LOAD_STORE,
+    FAULT_DANGLING_PTR,
+    FAULT_DOUBLE_FREE,
+    FAULT_INVALID_FREE,
+    FAULT_NOTHEAP_FREE,
+    FAULT_OUT_OF_BOUNDS,
+    FAULT_LOAD_STORE,
+    FAULT_ALIGN,
+    FAULT_WRITE_OUT_OF_BOUNDS,
+    FAULT_UNINIT,
+    FAULT_CSTDLIB
+  };
+
+  /// Type of violation
+  unsigned int type;
+
+  /// The program counter of the instruction generating the violations
+  const void * faultPC;
+
+  /// The pointer generating the violations
+  const void * faultPtr;
+
+  virtual void print(std::ostream & OS) const;
+  virtual ~ViolationInfo();
+};
+
+
+//
+// Function: ReportMemoryViolation()
+//
+// Description:
+//  Report a memory violation
+//
+void
+ReportMemoryViolation (const ViolationInfo * info);
+
+}
+
+#endif
Index: runtime/libsc/include/BitmapAllocator.h
===================================================================
--- runtime/libsc/include/BitmapAllocator.h	(revision 0)
+++ runtime/libsc/include/BitmapAllocator.h	(revision 0)
@@ -0,0 +1,128 @@
+//===- PoolAllocator.h - Pool allocator runtime interface file --*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface which is implemented by the LLVM pool
+// allocator runtime library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _PA_BITMAP_RUNTIME_H_
+#define _PA_BITMAP_RUNTIME_H_
+
+#include <string>
+#include <set>
+
+// Use a macro for the const attribute.  This allows const to be disabled for
+// debugging, allowing a programmer to change logregs during a debugging
+// session.
+#define CONST const
+
+/// It should be always zero in production version 
+/* Set to 1 to log object registrations */
+static CONST __attribute__((unused)) unsigned logregs = 0;
+
+namespace llvm {
+
+/// This structure is intended to be used by inheritance (synatatic sugar from
+/// C++), but it does not have a virtual destructor for it. Therefore you should
+/// never delete a BitmapPoolTy* directly!
+struct BitmapPoolTy {
+  static const unsigned AddrArrSize = 2;
+  // Linked list of slabs used for stack allocations
+  void * StackSlabs;
+
+  // Linked list of slabs available for stack allocations
+  void * FreeStackSlabs;
+
+  // Ptr1, Ptr2 - Implementation specified data pointers.
+  void *Ptr1, *Ptr2;
+
+  // FreeablePool - Set to false if the memory from this pool cannot be freed
+  // before destroy.
+  //
+  //  unsigned short FreeablePool;
+
+  //
+  // FIXME: Swithc this over to use tr1::unordered_set
+  // Use the hash_set only if the number of Slabs exceeds AddrArrSize
+  std::set<void*> *Slabs;
+
+  // The array containing the initial address of slabs (as long as there are
+  // fewer than a certain number of them)
+  void* SlabAddressArray[AddrArrSize];
+
+  // The number of slabs allocated. Large arrays are not counted
+  unsigned NumSlabs;
+
+  // TODO: Not sure for what this value is used.
+  unsigned short lastUsed;
+
+  // NodeSize - Keep track of the object size tracked by this pool
+  unsigned short NodeSize;
+
+  // Large arrays. In SAFECode, these are currently not freed or reused. 
+  // A better implementation could split them up into single slabs for reuse,
+  // upon being freed.
+  void *LargeArrays;
+  void *FreeLargeArrays;
+};
+
+#if 0
+/// Template class to implement
+/// realloc, calloc, strdup based on a particular implementation 
+/// of a pool allocator 
+template <class AllocatorT>
+class PoolAllocatorFacade {
+public:
+  typedef typename AllocatorT::PoolT PoolT;
+  static void * realloc(PoolT * Pool, void * Node, unsigned NumBytes) {
+    if (Node == 0) return AllocatorT::poolalloc(Pool, NumBytes);
+    if (NumBytes == 0) {
+      poolfree(Pool, Node);
+      return 0;
+    }
+
+    void *New = AllocatorT::poolalloc(Pool, NumBytes);
+    memcpy(New, Node, NumBytes);
+    AllocatorT::poolfree(Pool, Node);
+    return New;
+  }
+
+  static void * calloc(PoolT *Pool, unsigned Number, unsigned NumBytes) {
+    void * New = AllocatorT::poolalloc (Pool, Number * NumBytes);
+    if (New) bzero (New, Number * NumBytes);
+    return New;
+  } 
+
+  static void * strdup(PoolT *Pool, char *Node) {
+    if (Node == 0) return 0;
+
+    unsigned int NumBytes = strlen(Node) + 1;
+    void *New = AllocatorT::poolalloc(Pool, NumBytes);
+    if (New) {
+      memcpy(New, Node, NumBytes+1);
+    }
+    return New;
+  } 
+};
+#endif
+
+}
+
+/// Interfaces provided by the bitmap allocators
+extern "C" {
+  void __pa_bitmap_poolinit(llvm::BitmapPoolTy *Pool, unsigned NodeSize);
+  void __pa_bitmap_pooldestroy(llvm::BitmapPoolTy *Pool);
+  void * __pa_bitmap_poolalloc(llvm::BitmapPoolTy *Pool, unsigned NumBytes);
+  void * __pa_bitmap_poolstrdup(llvm::BitmapPoolTy *Pool, void *Node);
+  void __pa_bitmap_poolfree(llvm::BitmapPoolTy *Pool, void *Node);
+  void * __pa_bitmap_poolcheck(llvm::BitmapPoolTy *Pool, void *Node);
+}
+
+#endif
Index: runtime/libsc/include/PoolSystem.h
===================================================================
--- runtime/libsc/include/PoolSystem.h	(revision 0)
+++ runtime/libsc/include/PoolSystem.h	(revision 0)
@@ -0,0 +1,32 @@
+/*===- PoolSystem.h - Pool check runtime interface to the system ----------===*/
+/*                                                                            */
+/*                       The LLVM Compiler Infrastructure                     */
+/*                                                                            */
+/* This file was developed by the LLVM research group and is distributed      */
+/* under the University of Illinois Open Source License. See LICENSE.TXT for  */
+/* details.                                                                   */
+/*                                                                            */
+/*===----------------------------------------------------------------------===*/
+/*                                                                            */
+/*                                                                            */
+/*===----------------------------------------------------------------------===*/
+
+#ifndef POOLSYSTEM_RUNTIME_H
+#define POOLSYSTEM_RUNTIME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  /* Functions that need to be provided by the pool allocation run-time */
+  void poolcheckfail (const char * msg, int, void*) __attribute__ ((weak));
+  void poolcheckfatal (const char * msg, int) __attribute__ ((weak));
+  void poolcheckinfo (const char * msg, int) __attribute__ ((weak));
+  void poolcheckinfo2 (const char * msg, int, int) __attribute__ ((weak));
+  void * poolcheckmalloc (unsigned int size) __attribute__ ((weak));
+  void printpoolinfo (void *Pool) __attribute__ ((weak));
+  void poolcheckglobals ();
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: runtime/libsc/include/BBRuntime.h
===================================================================
--- runtime/libsc/include/BBRuntime.h	(revision 0)
+++ runtime/libsc/include/BBRuntime.h	(revision 0)
@@ -0,0 +1,177 @@
+//===- SAFECodeRuntime.h -- Runtime interface of SAFECode ------*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrast`ructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface of SAFECode runtime library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _BB_RUNTIME_H_
+#define _BB_RUNTIME_H_
+
+#include "BitmapAllocator.h"
+
+#include <iosfwd>
+
+namespace llvm {
+
+//
+// Enumerated Type: allocType
+//
+// Description:
+//  This enumerated type lists the different types of allocations that can be
+//  made.
+//
+enum allocType {
+  Global,   // Global object
+  Stack,    // Stack-allocated object
+  Heap      // Heap-allocated object
+};
+
+//
+// Structure: DebugMetaData
+//
+// Description:
+//  This structure contains information on the error to be reported.
+//
+// Fields:
+//  allocID    : The ID number of the allocation of the object.
+//  freeID     : The ID number of the deallocation of the object.
+//  allocPC    : The program counter at which the object was last allocated.
+//  freePC     : The program counter at which the object was last deallocated.
+//  canonAddr  : The canonical address of the memory reference.
+//  SourceFile : A string containing the source file to which the erring
+//               instruction is found.
+//  lineno     : The line number in the source file to which the erring
+//               instruction is found.
+//
+typedef struct DebugMetaData {
+  unsigned allocID;
+  unsigned freeID;
+  void * allocPC;
+  void * freePC;
+  void * canonAddr;
+
+  // Allocation type (global, stack, or heap object)
+  allocType allocationType;
+
+  // Source filename
+  void * SourceFile;
+
+  // Source filename for deallocation
+  void * FreeSourceFile;
+
+  // Line number
+  unsigned lineno;
+
+  // Line number for deallocation
+  unsigned Freelineno;
+
+  void print(std::ostream & OS) const;
+} DebugMetaData;
+typedef DebugMetaData * PDebugMetaData;
+
+struct DebugPoolTy : public BitmapPoolTy {
+};
+
+void * rewrite_ptr (DebugPoolTy * Pool, const void * p, const void * ObjStart,
+const void * ObjEnd, const char * SourceFile, unsigned lineno);
+void installAllocHooks (void);
+
+}
+
+// Use macros so that I won't polluate the namespace
+
+#define PPOOL NAMESPACE_SC::DebugPoolTy*
+#define TAG unsigned
+#define SRC_INFO const char *, unsigned int
+
+#define UNSET_MASK 0x7fffffffffff
+#define SET_MASK 0xffff800000000000
+
+extern "C" {
+  void pool_init_runtime(unsigned Dangling,
+                         unsigned RewriteOOB,
+                         unsigned Terminate);
+  void * __sc_bb_newpool(unsigned NodeSize);
+  void __sc_bb_pooldestroy(PPOOL);
+
+  void * __sc_bb_poolinit(PPOOL, unsigned NodeSize, unsigned);
+  void * __sc_bb_poolalloc(PPOOL, unsigned NumBytes);
+  void * __sc_bb_src_poolalloc (PPOOL, unsigned Size, TAG, SRC_INFO);
+
+  void * __sc_bb_poolargvregister (int argc, char ** argv);
+
+  void __sc_bb_poolregister(PPOOL, void *allocaptr, unsigned NumBytes);
+  void __sc_bb_src_poolregister (PPOOL, void * p, unsigned size, TAG, SRC_INFO);
+  void __sc_bb_poolregister_stack (PPOOL, void * p, unsigned size);
+  void __sc_bb_src_poolregister_stack (PPOOL, void * p, unsigned size, TAG, SRC_INFO);
+  void __sc_bb_poolregister_global (PPOOL, void * p, unsigned size);
+  void __sc_bb_src_poolregister_global_debug (PPOOL, void * p, unsigned size, TAG, SRC_INFO);
+
+  void __sc_bb_poolunregister(PPOOL, void *allocaptr);
+  void __sc_bb_poolunregister_stack(PPOOL, void *allocaptr);
+  void __sc_bb_poolunregister_debug(PPOOL, void *allocaptr, TAG, SRC_INFO);
+  void __sc_bb_poolunregister_stack_debug(PPOOL, void *allocaptr, TAG, SRC_INFO);
+  void __sc_bb_poolfree(PPOOL, void *Node);
+  void __sc_bb_src_poolfree (PPOOL, void *, TAG, SRC_INFO);
+
+  void * __sc_bb_poolcalloc (PPOOL, unsigned Number, unsigned NumBytes, TAG);
+  void * __sc_bb_src_poolcalloc (PPOOL,
+                                unsigned Number, unsigned NumBytes,
+                                  TAG, SRC_INFO);
+
+  void * __sc_bb_poolrealloc(PPOOL, void *Node, unsigned NumBytes);
+  void * __sc_bb_poolrealloc_debug(PPOOL, void *Node, unsigned NumBytes, TAG, SRC_INFO);
+  void * __sc_bb_poolstrdup (PPOOL, const char * Node);
+  void * __sc_bb_poolstrdup_debug (PPOOL, const char * Node, TAG, SRC_INFO);
+  void * __sc_bb_poolmemalign(PPOOL, unsigned Alignment, unsigned NumBytes);
+
+  void bb_poolcheck(PPOOL, void *Node);
+  void bb_poolcheckui(PPOOL, void *Node);
+  void bb_poolcheck_debug (PPOOL, void * Node, TAG, SRC_INFO);
+  void bb_poolcheckui_debug(PPOOL, void *Node, TAG, SRC_INFO);
+
+  void bb_poolcheckalign(PPOOL, void *Node, unsigned Offset);
+  void bb_poolcheckalign_debug (PPOOL, void *Node, unsigned Offset, TAG, SRC_INFO);
+
+  void * bb_boundscheck   (PPOOL, void * Source, void * Dest);
+  void * bb_boundscheckui (PPOOL, void * Source, void * Dest);
+  void * bb_boundscheckui_debug (PPOOL, void * S, void * D, TAG, SRC_INFO);
+  void * bb_boundscheck_debug (PPOOL, void * S, void * D, TAG, SRC_INFO);
+
+  // CStdLib
+  void * bb_pool_memcpy(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, size_t n);
+  void * bb_pool_memmove(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, size_t n);
+  void * bb_pool_memset(PPOOL sPool, void *s, int c, size_t n);
+  char * bb_pool_strcpy(PPOOL dstPool, PPOOL srcPool, char *dst, const char *src);
+  char * bb_pool_strcpy_debug(PPOOL dstPool, PPOOL srcPool, char *dst, const char *src, TAG, SRC_INFO);
+  size_t bb_pool_strlen(PPOOL stringPool, const char *string);
+  char * pool_strncpy(PPOOL dstPool, PPOOL srcPool, char *dst, const char *src, size_t n);
+
+#ifdef _GNU_SOURCE
+  void * bb_pool_mempcpy(PPOOL dstPool, PPOOL srcPool, void *dst, const void *src, size_t n);
+#endif
+
+  // Exact checks
+  void * bb_exactcheck2 (const char *base, const char *result, unsigned size);
+  void * bb_exactcheck2_debug (const char *base, const char *result, unsigned size,
+                            TAG, SRC_INFO);
+
+  void __sc_bb_funccheck (unsigned num, void *f, void *g, ...);
+  void * pchk_getActualValue (PPOOL, void * src);
+
+  // Change memory protections to detect dangling pointers
+  void * bb_pool_shadow (void * Node, unsigned NumBytes);
+  void * bb_pool_unshadow (void * Node);
+}
+
+#undef PPOOL
+#undef TAG
+#undef SRC_INFO
+#endif
Index: runtime/libsc/include/MMAPSupport.h
===================================================================
--- runtime/libsc/include/MMAPSupport.h	(revision 0)
+++ runtime/libsc/include/MMAPSupport.h	(revision 0)
@@ -0,0 +1,58 @@
+//===- MMAPSupport.h - mmap portability wrappers ----------------*- C++ -*-===//
+// 
+//                       The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file allows clients to use some functionality of mmap efficiently and
+// portably.  This is used for the pool allocator runtime implementations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+
+#include <cstdlib>
+#include <cassert>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+#define MAP_ANONYMOUS MAP_ANON
+#endif /* defined(MAP_ANON) && !defined(MAP_ANONYMOUS) */
+
+static inline void *
+AllocateSpaceWithMMAP(size_t Size, bool UseNoReserve = false) {
+  // NOTE: this assumes Size is a multiple of the page size.
+  int FD = -1;
+#ifdef NEED_DEV_ZERO_FOR_MMAP
+  static int DevZeroFD = open("/dev/zero", O_RDWR);
+  if (DevZeroFD == -1) {
+    perror("Can't open /dev/zero device");
+    abort();
+  }
+  FD = zero_fd;
+#endif
+
+  int Flags = MAP_PRIVATE | MAP_ANONYMOUS;
+#ifdef MAP_NORESERVE
+  if (UseNoReserve)
+    Flags |= MAP_NORESERVE;
+#endif
+
+  void *Mem = ::mmap(0, Size, PROT_READ|PROT_WRITE, Flags, FD, 0);
+  assert(Mem != MAP_FAILED && "couldn't get space!");
+  return Mem;
+}
Index: runtime/libsc/include/PageManager.h
===================================================================
--- runtime/libsc/include/PageManager.h	(revision 0)
+++ runtime/libsc/include/PageManager.h	(revision 0)
@@ -0,0 +1,103 @@
+//===- PageManager.h - Allocates memory on page boundaries ------*- C++ -*-===//
+// 
+//                          The SAFECode Compiler 
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface used by the pool allocator to allocate memory
+// on large alignment boundaries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PAGEMANAGER_H
+#define PAGEMANAGER_H
+
+#include <stdint.h>
+
+#include <vector>
+
+namespace llvm {
+
+//
+// Value used to initialize memory.
+//    o Linux : We use the reserved address space for the kernel.
+//    o Others: We use the first page in memory (aka zero page).
+//
+#if defined(__linux__)
+static const unsigned initvalue = 0xcc;
+#else
+static const unsigned initvalue = 0x00;
+#endif
+
+/// PageMultipler - This variable holds the ratio between physical pages and
+/// the number of pages returned by AllocatePage.
+///
+/// NOTE:
+///   The size of a page returned from AllocatePage *must* be under 64K.  This
+///   is because the pool slab using 16 bit integers to index into the slab.
+#define PAGEMULT 16
+static const unsigned int PageMultiplier=PAGEMULT;
+
+/// NumToAllocate - This variable specifies the number of pages of size
+///                 PageMultipler to allocate at a time.
+static const unsigned NumToAllocate = 8;
+
+/// NumShadows - This variable specifies the number of shadows that should be
+/// created automatically for every piece of memory created by AllocatePage().
+static const unsigned int NumShadows=4;
+
+/// InitializePageManager - This function must be called before any other page
+/// manager accesses are performed.  It may be called multiple times.
+/// 
+void InitializePageManager();
+
+void *GetPages(unsigned NumPages);
+
+/// PageSize - Contains the size of the unit of memory allocated by
+/// AllocatePage.  This is a value that is typically several kilobytes in size,
+/// and is guaranteed to be a power of two.
+///
+extern "C" uintptr_t PageSize;
+
+/// PPageSize - Contains the size of a single physical page.  This is the
+/// smallest granularity at which virtual memory operations can be performed.
+extern uintptr_t PPageSize;
+
+/// AllocatePage - This function returns a chunk of memory with size and
+/// alignment specified by getPageSize().
+void * AllocatePage();
+
+// RemapObject - This function is used by the dangling pool allocator in order
+//               to remap canonical pages to shadow pages.
+void * RemapObject(void* va, unsigned NumByte);
+
+/// AllocateNPages - Allocates Num number of pages
+void *AllocateNPages(unsigned Num);
+
+// MProtectPage - Protects Page passed in by argument, raising an exception
+//                or traps at future access to Page
+void MProtectPage(void * Page, unsigned NumPages);
+
+// ProtectShadowPage - Protects shadow page that begins at beginAddr, spanning
+//                     over NumPages
+void ProtectShadowPage(void * beginPage, unsigned NumPPages);
+
+// UnprotectShadowPage - Unprotects the shadow page in the event of fault when
+//                       accessing protected shadow page in order to
+//                       resume execution
+void UnprotectShadowPage(void * beginPage, unsigned NumPPage);
+
+/// FreePage - This function returns the specified page to the pagemanager for
+/// future allocation.
+void FreePage(void *Page);
+
+// The set of free memory pages we retrieved from the OS.
+typedef std::vector<void*> FreePagesListType;
+extern FreePagesListType FreePages;
+
+}
+
+#endif
Index: runtime/libsc/include/MallocAllocator.h
===================================================================
--- runtime/libsc/include/MallocAllocator.h	(revision 0)
+++ runtime/libsc/include/MallocAllocator.h	(revision 0)
@@ -0,0 +1,93 @@
+//===-- llvm/Support/MallocAllocator.h --------------------------*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines MallocAllocator class, an STL compatible allocator which
+// just uses malloc/free to get and release memory.  The default allocator uses
+// the STL pool allocator runtime library, this explicitly avoids it.
+//
+// This file is used for variety of purposes, including the pool allocator
+// project and testing, regardless of whether or not it's used directly in the
+// LLVM code, so don't delete this from CVS if you think it's unused!
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MALLOCALLOCATOR_H
+#define LLVM_SUPPORT_MALLOCALLOCATOR_H
+
+#include <cstdlib>
+#include <memory>
+
+namespace llvm {
+
+template<typename T>
+struct MallocAllocator {
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+  typedef T* pointer;
+  typedef const T* const_pointer;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef T value_type;
+  template <class U> struct rebind {
+    typedef MallocAllocator<U> other;
+  };
+
+  template<typename R>
+  MallocAllocator(const MallocAllocator<R> &) {}
+  MallocAllocator() {}
+
+  pointer address(reference x) const { return &x; }
+  const_pointer address(const_reference x) const { return &x; }
+  size_type max_size() const { return ~0 / sizeof(T); }
+  
+  static pointer allocate(size_t n, void* hint = 0) {
+    return static_cast<pointer>(malloc(n*sizeof(T)));
+  }
+
+  static void deallocate(pointer p, size_t n) {
+    free(static_cast<void*>(p));
+  }
+
+  void construct(pointer p, const T &val) {
+    new(static_cast<void*>(p)) T(val);
+  }
+  void destroy(pointer p) {
+    p->~T();
+  }
+};
+
+template<typename T>
+inline bool operator==(const MallocAllocator<T> &, const MallocAllocator<T> &) {
+  return true;
+}
+template<typename T>
+inline bool operator!=(const MallocAllocator<T>&, const MallocAllocator<T>&) {
+  return false;
+}
+} // End llvm namespace
+
+/*
+ * This specialization was used for optimization earlier, but doesn't appear
+ * to work with newer versions of GCC, Linux or otherwise.
+ *
+ * This can be re-enabled if desired, but by default, it won't be included.
+ */ 
+#if 0
+namespace std {
+  template<typename Type, typename Type2>
+  struct _Alloc_traits<Type, ::llvm::MallocAllocator<Type2> > {
+    static const bool _S_instanceless = true;
+    typedef ::llvm::MallocAllocator<Type> base_alloc_type;
+    typedef ::llvm::MallocAllocator<Type> _Alloc_type;
+    typedef ::llvm::MallocAllocator<Type> allocator_type;
+  };
+}
+#endif
+
+#endif
Index: runtime/libsc/include/SplayTree.h
===================================================================
--- runtime/libsc/include/SplayTree.h	(revision 0)
+++ runtime/libsc/include/SplayTree.h	(revision 0)
@@ -0,0 +1,331 @@
+//===-- SplayTree.h - Splay Tree Implementation -----------------*- C++ -*-===//
+// 
+//                         Automatic Pool Allocation
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements several splay tree classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include <memory>
+#include <vector>
+
+#ifndef SUPPORT_SPLAYTREE_H
+#define SUPPORT_SPLAYTREE_H
+
+template<typename dataTy>
+struct range_tree_node {
+  range_tree_node(void* s, void* e) : left(0), right(0), start(s), end(e) {}
+  range_tree_node() : left(0), right(0), start(0), end(0) {}
+  template<class O>
+  void do_act(O& act) { act(start, end, data); }
+  range_tree_node* left;
+  range_tree_node* right;
+  void* start;
+  void* end;
+  dataTy data;
+};
+
+template<>
+struct range_tree_node <void>{
+  range_tree_node(void* s, void* e) : left(0), right(0), start(s), end(e) {}
+  range_tree_node() : left(0), right(0), start(0), end(0) {}
+  template<class O>
+  void do_act(O& act) { act(start, end); }
+  range_tree_node* left;
+  range_tree_node* right;
+  void* start;
+  void* end;
+};
+
+template<typename T, class _Alloc>
+class RangeSplayTree {
+ public:
+  typedef range_tree_node<T> tree_node;
+ private:
+  typename _Alloc::template rebind<tree_node >::other __node_alloc;
+  
+  tree_node* Tree;
+    
+  tree_node* rotate_right(tree_node* p) {
+    tree_node* x = p->left;
+    p->left = x->right;
+    x->right = p;
+    return x;
+  }
+
+  tree_node* rotate_left(tree_node* p) {
+    tree_node* x = p->right;
+    p->right = x->left;
+    x->left = p;
+    return x;
+  }
+
+  bool key_lt(void* _key, tree_node* _t) { return _key < _t->start; };
+
+  bool key_gt(void* _key, tree_node* _t) { return _key > _t->end; };
+
+  /* This function by D. Sleator <sleator@cs.cmu.edu> */
+  tree_node* splay (tree_node * t, void* key) {
+    tree_node N, *l, *r, *y;
+    if (t == 0) return t;
+    N.left = N.right = 0;
+    l = r = &N;
+    
+    while(1) {
+      if (key_lt(key, t)) {
+        if (t->left == 0) break;
+        if (key_lt(key, t->left)) {
+          y = t->left;                           /* rotate right */
+          t->left = y->right;
+          y->right = t;
+          t = y;
+          if (t->left == 0) break;
+        }
+        r->left = t;                               /* link right */
+        r = t;
+        t = t->left;
+      } else if (key_gt(key, t)) {
+        if (t->right == 0) break;
+        if (key_gt(key, t->right)) {
+          y = t->right;                          /* rotate left */
+          t->right = y->left;
+          y->left = t;
+          t = y;
+          if (t->right == 0) break;
+        }
+        l->right = t;                              /* link left */
+        l = t;
+        t = t->right;
+      } else {
+        break;
+      }
+    }
+    l->right = t->left;                                /* assemble */
+    r->left = t->right;
+    t->left = N.right;
+    t->right = N.left;
+    return t;
+  }
+
+  unsigned count_internal(tree_node* t) {
+    if (t)
+      return 1 + count_internal(t->left) + count_internal(t->right);
+    return 0;
+  }
+
+  void __clear_internal(tree_node* tree) {
+    //
+    // If there is no node, then simply return.
+    //
+    if (!tree) return;
+
+    // The set of elements yet to process
+    std::vector<tree_node *> stack;
+    stack.push_back (tree);
+
+    //
+    // Begin deleting elements.
+    //
+    while (stack.size()) {
+      //
+      // Remove the last node of the tree.
+      //
+      tree_node * t = stack.back();
+      stack.pop_back();
+
+      //
+      // Push on to the stack for later processing the children.
+      //
+      if (t->left)  stack.push_back (t->left);
+      if (t->right) stack.push_back (t->right);
+
+      //
+      // Delete the element.
+      //
+      __node_alloc.destroy(t);
+      __node_alloc.deallocate(t, 1);
+    }
+  }
+
+  template<class O>
+  void __clear_internal(tree_node* t, O& act) {
+    if (!t) return;
+    __clear_internal(t->left);
+    __clear_internal(t->right);
+    t->do_act(act);
+    __node_alloc.destroy(t);
+    __node_alloc.deallocate(t, 1);
+  }
+
+ public:
+
+  explicit RangeSplayTree(const _Alloc& a) :__node_alloc(a), Tree(0) {}
+  ~RangeSplayTree() { __clear(); }
+  
+  tree_node* __insert(void* start, void* end) {
+    Tree = splay(Tree, start);
+    //If the key is already in, fail the insert
+    if (Tree && !key_lt(start, Tree) && !key_gt(start, Tree))
+      return 0;
+    
+    tree_node* n = __node_alloc.allocate(1);
+    __node_alloc.construct(n, tree_node(start,end));
+    if (Tree) {
+      if (key_lt(start, Tree)) {
+        n->left = Tree->left;
+        n->right = Tree;
+        Tree->left = 0;
+      } else {
+        n->right = Tree->right;
+        n->left = Tree;
+        Tree->right = 0;
+      }
+    }
+    Tree = n;
+    return Tree;
+  }
+
+  bool __remove(void* key) {
+    if (!Tree) return false;
+    Tree = splay(Tree, key);
+    if (!key_lt(key, Tree) && !key_gt(key, Tree)) {
+      tree_node* x = 0;
+      if (!Tree->left)
+        x = Tree->right;
+      else {
+        x = splay(Tree->left, key);
+        x->right = Tree->right;
+      }
+      tree_node* y = Tree;
+      Tree = x;
+      __node_alloc.destroy(y);
+      __node_alloc.deallocate(y, 1);
+      return true;
+    }
+    return false; /* not there */
+  }
+
+  unsigned __count() {
+    return count_internal(Tree);
+  }
+
+  void __clear() {
+    __clear_internal(Tree);
+    Tree = 0;
+  }
+
+  template <class O>
+  void __clear(O& act) { 
+    __clear_internal(Tree, act);
+    Tree = 0;
+  }
+
+  tree_node* __find(void* key) {
+    if (!Tree) return false;
+    Tree = splay(Tree, key);
+    if (!key_lt(key, Tree) && !key_gt(key, Tree)) {
+      return Tree;
+    }
+    return 0;
+  }
+};
+
+template<class Allocator = std::allocator<void> >
+class RangeSplaySet 
+{
+  RangeSplayTree<void, Allocator> Tree;
+
+ public:
+  explicit RangeSplaySet(const Allocator& A = Allocator() )
+  : Tree(A) {}
+  
+  //
+  // Method: insert()
+  //
+  // Description:
+  //  Insert an element into the splay set.
+  //
+  // Inputs:
+  //  start - The first valid address of the object.
+  //  end   - The last valid address of the object.
+  //
+  // Return value:
+  //  true  - The insert succeeded.
+  //  false - The insert failed.
+  //
+  bool insert(void* start, void* end) {
+    return 0 != Tree.__insert(start,end);
+  }
+  
+  bool remove(void* key) {
+    return Tree.__remove(key);
+  }
+
+  unsigned count() { return Tree.__count(); }
+
+  void clear() { Tree.__clear(); }
+
+  template <class O>
+  void clear(O& act) { Tree.__clear(act); }
+
+  bool find(void* key, void*& start, void*& end) {
+    range_tree_node<void>* t = Tree.__find(key);
+    if (!t) return false;
+    start = t->start;
+    end = t->end;
+    return true;
+  }
+  bool find(void* key) {
+    range_tree_node<void>* t = Tree.__find(key);
+    if (!t) return false;
+    return true;
+  }
+};
+
+template<typename T, class Allocator = std::allocator<T> >
+class RangeSplayMap {
+  RangeSplayTree<T, Allocator> Tree;
+  
+  public:
+  explicit RangeSplayMap(const Allocator& A= Allocator() ) 
+  : Tree(A) {}
+  
+  bool insert(void* start, void* end, const T& d) {
+    range_tree_node<T>* t = Tree.__insert(start,end);
+    if (t == 0) return false;
+    t->data = d;
+    return true;
+  }
+  
+  bool remove(void* key) {
+    return Tree.__remove(key);
+  }
+  
+  unsigned count() { return Tree.__count(); }
+  
+  void clear() { Tree.__clear(); }
+  
+  template <class O>
+  void clear(O& act) { Tree.__clear(act); }
+  
+  bool find(void* key, void*& start, void*& end, T& d) {
+    range_tree_node<T>* t = Tree.__find(key);
+    if (!t) return false;
+    start = t->start;
+    end = t->end;
+    d = t->data;
+    return true;
+  }
+  bool find(void* key) {
+    range_tree_node<T>* t = Tree.__find(key);
+    if (!t) return false;
+    return true;
+  }
+};
+
+#endif
Index: runtime/libsc/BitmapPoolAllocator/PoolSlab.h
===================================================================
--- runtime/libsc/BitmapPoolAllocator/PoolSlab.h	(revision 0)
+++ runtime/libsc/BitmapPoolAllocator/PoolSlab.h	(revision 0)
@@ -0,0 +1,261 @@
+//===- PoolSlab.h - --*- C++ -*--------------------------------------------===//
+// 
+//                          The SAFECode Compiler
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file declares the interfaces of slabs which used by pool allocators.
+//
+// This uses the 'Ptr1' field to maintain a linked list of slabs that are either
+// empty or are partially allocated from.  The 'Ptr2' field of the PoolTy is
+// used to track a linked list of slabs which are full, ie, all elements have
+// been allocated from them.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _POOLSLAB_H_
+#define _POOLSLAB_H_
+
+#include "../include/BitmapAllocator.h"
+#include "../include/PageManager.h"
+
+#include <cassert>
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+//
+//  PoolSlab implementation
+//
+//===----------------------------------------------------------------------===//
+
+// PoolSlab Structure - Hold multiple objects of the current node type.
+// Invariants: FirstUnused <= UsedEnd
+//
+struct PoolSlab {
+  PoolSlab **PrevPtr, *Next;
+  bool isSingleArray;   // If this slab is used for exactly one array
+  unsigned allocated; // Number of bytes allocated
+  PoolSlab * Canonical; // For stack slabs, the canonical page
+
+private:
+  // FirstUnused - First empty node in slab
+  unsigned short FirstUnused;
+
+  // UsedBegin - The first node in the slab that is used.
+  unsigned short UsedBegin;
+
+  // UsedEnd - 1 past the last allocated node in slab. 0 if slab is empty
+  unsigned short UsedEnd;
+
+  // NumNodesInSlab - This contains the number of nodes in this slab, which
+  // effects the size of the NodeFlags vector, and indicates the number of nodes
+  // which are in the slab.
+  unsigned int NumNodesInSlab;
+
+  // Size of Slab - For single array slabs, specifies the size of the slab in
+  //                bytes from beginning to end (including slab header).
+  //
+public:
+  unsigned int SizeOfSlab;
+
+private:
+  // NodeFlagsVector - This array contains two bits for each node in this pool
+  // slab.  The first (low address) bit indicates whether this node has been
+  // allocated, and the second (next higher) bit indicates whether this is the
+  // start of an allocation.
+  //
+  // This is a variable sized array, which has 2*NumNodesInSlab bits (rounded up
+  // to 4 bytes).
+  unsigned NodeFlagsVector[1];
+  
+  bool isNodeAllocated(unsigned NodeNum) {
+    return NodeFlagsVector[NodeNum/16] & (1 << (NodeNum & 15));
+  }
+
+  void markNodeAllocated(unsigned NodeNum) {
+    NodeFlagsVector[NodeNum/16] |= 1 << (NodeNum & 15);
+  }
+
+  void markNodeFree(unsigned NodeNum) {
+    NodeFlagsVector[NodeNum/16] &= ~(1 << (NodeNum & 15));
+  }
+
+  void setStartBit(unsigned NodeNum) {
+    NodeFlagsVector[NodeNum/16] |= 1 << ((NodeNum & 15)+16);
+  }
+
+public:
+  bool isStartOfAllocation(unsigned NodeNum) {
+    return NodeFlagsVector[NodeNum/16] & (1 << ((NodeNum & 15)+16));
+  }
+  
+private:
+  void clearStartBit(unsigned NodeNum) {
+    NodeFlagsVector[NodeNum/16] &= ~(1 << ((NodeNum & 15)+16));
+  }
+
+  void assertOkay (void) {
+    assert (FirstUnused <= UsedEnd);
+    assert ((UsedEnd == getSlabSize()) || (!isNodeAllocated(UsedEnd)));
+    assert ((FirstUnused == getSlabSize()) || (!isNodeAllocated(FirstUnused)));
+  }
+public:
+  // create - Create a new (empty) slab and add it to the end of the Pools list.
+  static PoolSlab *create(BitmapPoolTy *Pool);
+
+  // createSingleArray - Create a slab for a large singlearray with NumNodes
+  // entries in it, returning the pointer into the pool directly.
+  static void *createSingleArray(BitmapPoolTy  *Pool, unsigned NumNodes);
+
+  // getSlabSize - Return the number of nodes that each slab should contain.
+  static unsigned getSlabSize(BitmapPoolTy  *Pool) {
+    // We need space for the header...
+    unsigned NumNodes = PageSize-sizeof(PoolSlab);
+    
+    // We need space for the NodeFlags...
+    // FIXME:
+    //  We unconditionally round up a byte.  We should only do that if
+    //  necessary.
+    unsigned NodeFlagsBytes = (NumNodes/Pool->NodeSize * 2 / 8) + 1;
+    NumNodes -= (NodeFlagsBytes+3) & ~3;  // Round up to int boundaries.
+
+    // Divide the remainder among the nodes!
+    return NumNodes / Pool->NodeSize;
+  }
+
+  void addToList(PoolSlab **PrevPtrPtr) {
+    PoolSlab *InsertBefore = *PrevPtrPtr;
+    *PrevPtrPtr = this;
+    PrevPtr = PrevPtrPtr;
+    Next = InsertBefore;
+    if (InsertBefore) InsertBefore->PrevPtr = &Next;
+  }
+
+  void unlinkFromList() {
+    *PrevPtr = Next;
+    if (Next) Next->PrevPtr = PrevPtr;
+  }
+
+  unsigned getSlabSize() const {
+    return NumNodesInSlab;
+  }
+
+  // destroy - Release the memory for the current object.
+  void destroy();
+
+  // isEmpty - This is a quick check to see if this slab is completely empty or
+  // not.
+  bool isEmpty() const { return UsedEnd == 0; }
+
+  // isFull - This is a quick check to see if the slab is completely allocated.
+  //
+  bool isFull() const { return isSingleArray || (FirstUnused == getSlabSize()); }
+
+  // allocateSingle - Allocate a single element from this pool, returning -1 if
+  // there is no space.
+  int allocateSingle();
+
+  // allocateMultiple - Allocate multiple contiguous elements from this pool,
+  // returning -1 if there is no space.
+  int allocateMultiple(unsigned Num);
+
+  // getElementAddress - Return the address of the specified element.
+  void *getElementAddress(unsigned ElementNum, unsigned ElementSize) {
+    char *Data = (char*)&NodeFlagsVector[((unsigned)NumNodesInSlab+15)/16];
+    return &Data[ElementNum*ElementSize];
+  }
+  
+  const void *getElementAddress(unsigned ElementNum, unsigned ElementSize)const{
+    const char *Data =
+      (const char *)&NodeFlagsVector[(unsigned)(NumNodesInSlab+15)/16];
+    return &Data[ElementNum*ElementSize];
+  }
+
+  // containsElement - Return the element number of the specified address in
+  // this slab.  If the address is not in slab, return -1.
+  int containsElement(void *Ptr, unsigned ElementSize) const;
+
+  // freeElement - Free the single node, small array, or entire array indicated.
+  void freeElement(unsigned short ElementIdx);
+  
+  // getSize --- size of an allocation
+  unsigned getSize(void *Node, unsigned ElementSize);
+  
+  // lastNodeAllocated - Return one past the last node in the pool which is
+  // before ScanIdx, that is allocated.  If there are no allocated nodes in this
+  // slab before ScanIdx, return 0.
+  unsigned lastNodeAllocated(unsigned ScanIdx);
+};
+
+//===----------------------------------------------------------------------===//
+//
+//  StackSlab implementation
+//
+//===----------------------------------------------------------------------===//
+
+//
+// Structure: StackSlab
+//
+// Description:
+//  A stack slab is similar to a pool slab but simple and smaller.  It is used
+//  for stack allocations that have been promoted to the heap.
+struct StackSlab {
+public:
+  // Pointer to canonical address of stack slab
+  StackSlab * Canonical;
+
+  // Pointers for linking in the stack slab
+  StackSlab **PrevPtr, *Next;
+
+  // Top of stack
+  unsigned int * tos;
+
+  // Data for the stack
+  unsigned int data[1020];
+
+  static StackSlab *create (void * p) {
+    StackSlab *SS = (StackSlab*) p;
+    SS->tos = &(SS->data[0]);
+    return SS;
+  }
+
+  unsigned char * allocate (unsigned int size) {
+    //
+    // We will return a pointer to the current top of stack.
+    //
+    unsigned char * retvalue = (unsigned char *) (tos);
+
+    //
+    // Adjust the top of stack down to the next free object.
+    //
+    size = (size + 3) & (~3u);
+    unsigned int NumberOfInts = size / sizeof (unsigned int);
+    tos += NumberOfInts;
+    assert (tos < &(data[1020]));
+    return retvalue;
+  }
+
+  void clear (void) {
+    tos = data;
+  }
+
+  void addToList(StackSlab **PrevPtrPtr) {
+    StackSlab *InsertBefore = *PrevPtrPtr;
+    *PrevPtrPtr = this;
+    PrevPtr = PrevPtrPtr;
+    Next = InsertBefore;
+    if (InsertBefore) InsertBefore->PrevPtr = &Next;
+  }
+
+  void unlinkFromList() {
+    *PrevPtr = Next;
+    if (Next) Next->PrevPtr = PrevPtr;
+  }
+};
+
+}
+#endif
Index: runtime/libsc/BitmapPoolAllocator/PoolAllocatorBitMask.cpp
===================================================================
--- runtime/libsc/BitmapPoolAllocator/PoolAllocatorBitMask.cpp	(revision 0)
+++ runtime/libsc/BitmapPoolAllocator/PoolAllocatorBitMask.cpp	(revision 0)
@@ -0,0 +1,504 @@
+//===- PoolAllocatorBitMask.cpp - Implementation of poolallocator runtime -===//
+// 
+//                          The SAFECode Compiler
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file is one possible implementation of the LLVM pool allocator runtime
+// library.
+//
+// This uses the 'Ptr1' field to maintain a linked list of slabs that are either
+// empty or are partially allocated from.  The 'Ptr2' field of the BitmapPoolTy is
+// used to track a linked list of slabs which are full, ie, all elements have
+// been allocated from them.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../include/BitmapAllocator.h"
+#include "../include/PageManager.h"
+#include "PoolSlab.h"
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#define DEBUG(x)
+
+using namespace llvm;
+
+/// Helper functions
+
+static void *
+poolallocarray(BitmapPoolTy* Pool, unsigned Size);
+
+static PoolSlab *
+SearchForContainingSlab(BitmapPoolTy *Pool, void *Node, unsigned &TheIndex);
+
+//
+// Function: poolinit()
+//
+// Description:
+//  Initialize the specified pool descriptor.  Pool descriptors are either
+//  global variables or alloca'ed memory created by instrumentation added by
+//  the SAFECode passes.  This function initializes all of the fields of the
+//  pool descriptor.
+//
+void
+__pa_bitmap_poolinit(BitmapPoolTy *Pool, unsigned NodeSize) {
+  assert(Pool && "Null pool pointer passed into poolinit!\n");
+  DEBUG(printf("pool init %x, %d\n", Pool, NodeSize);)
+
+  // Ensure the page manager is initialized
+  InitializePageManager();
+
+  // We must alway return unique pointers, even if they asked for 0 bytes
+  Pool->NodeSize = NodeSize ? NodeSize : 1;
+  // Initialize the splay tree
+  Pool->Ptr1 = Pool->Ptr2 = 0;
+  Pool->LargeArrays = 0;
+  Pool->StackSlabs = Pool->FreeStackSlabs = 0;
+  // For SAFECode, we set FreeablePool to 0 always
+  //  Pool->FreeablePool = 0;
+  Pool->lastUsed = 0;
+  // Initialize the SlabAddressArray to zero
+  for (unsigned i = 0; i < BitmapPoolTy::AddrArrSize; ++i) {
+    Pool->SlabAddressArray[i] = 0;
+  }
+  Pool->NumSlabs = 0;
+}
+
+// pooldestroy - Release all memory allocated for a pool
+//
+// FIXME: determine how to adjust debug logs when 
+//        pooldestroy is called
+void
+__pa_bitmap_pooldestroy(BitmapPoolTy *Pool) {
+  assert(Pool && "Null pool pointer passed in to pooldestroy!\n");
+
+  if (Pool->NumSlabs > BitmapPoolTy::AddrArrSize) {
+    Pool->Slabs->clear();
+    delete Pool->Slabs;
+  }
+
+  // Free any partially allocated slabs
+  PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+  while (PS) {
+    PoolSlab *Next = PS->Next;
+    PS->destroy();
+    PS = Next;
+  }
+
+  // Free the completely allocated slabs
+  PS = (PoolSlab*)Pool->Ptr2;
+  while (PS) {
+    PoolSlab *Next = PS->Next;
+    PS->destroy();
+    PS = Next;
+  }
+
+  // Free the large arrays
+  PS = (PoolSlab*)Pool->LargeArrays;
+  while (PS) {
+    PoolSlab *Next = PS->Next;
+    PS->destroy();
+    PS = Next;
+  }
+
+}
+
+//
+// Function: poolalloc()
+//
+// Description:
+//  Allocate memory from the specified pool with the specified size.
+//
+// Inputs:
+//  Pool - The pool from which to allocate the memory.
+//  Size - The size, in bytes, of the memory object to allocate.  This does
+//         *not* need to match the size of the objects found in the pool.
+//
+void *
+__pa_bitmap_poolalloc(BitmapPoolTy *Pool, unsigned NumBytes) {
+  void *retAddress = NULL;
+  assert(Pool && "Null pool pointer passed into poolalloc!\n");
+
+  // FIXME: Is it necessary?
+  // Ensure that we're always allocating at least 1 byte.
+  if (NumBytes == 0)
+    NumBytes = 1;
+
+  //
+  // Calculate the number of nodes within the pool to allocate for an object
+  // of the specified size.
+  //
+  unsigned NodeSize = Pool->NodeSize;
+  assert (NodeSize && "__pa_bitmap_poolalloc: Node Size is zero!\n");
+  unsigned NodesToAllocate = (NumBytes + NodeSize - 1) / NodeSize;
+  
+  // Call a helper function if we need to allocate more than 1 node.
+  if (NodesToAllocate > 1) {
+    if (logregs) {
+      fprintf(stderr, " poolalloc:848: Allocating more than 1 node for %d bytes\n", NumBytes); fflush(stderr);
+    }
+
+    //
+    // Allocate the memory.
+    //
+    retAddress = poolallocarray(Pool, NodesToAllocate);
+      
+    assert (retAddress && "poolalloc(1): Returning NULL!\n");
+    return retAddress;
+  }
+
+  // Special case the most common situation, where a single node is being
+  // allocated.
+  PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+
+  if (__builtin_expect(PS != 0, 1)) {
+    int Element = PS->allocateSingle();
+    if (__builtin_expect(Element != -1, 1)) {
+      // We allocated an element.  Check to see if this slab has been
+      // completely filled up.  If so, move it to the Ptr2 list.
+      if (__builtin_expect(PS->isFull(), false)) {
+        PS->unlinkFromList();
+        PS->addToList((PoolSlab**)&Pool->Ptr2);
+      }     
+      return PS->getElementAddress(Element, NodeSize);
+    }
+
+    // Loop through all of the slabs looking for one with an opening
+    for (PS = PS->Next; PS; PS = PS->Next) {
+      int Element = PS->allocateSingle();
+      if (Element != -1) {
+        // We allocated an element.  Check to see if this slab has been
+        // completely filled up.  If so, move it to the Ptr2 list.
+        if (PS->isFull()) {
+          PS->unlinkFromList();
+          PS->addToList((PoolSlab**)&Pool->Ptr2);
+        }
+        return PS->getElementAddress(Element, NodeSize);
+      }
+    }
+  }
+
+  // Otherwise we must allocate a new slab and add it to the list
+  PoolSlab *New = PoolSlab::create(Pool);
+
+  //
+  // Ensure that we're always allocating at least 1 byte.
+  //
+  if (NumBytes == 0)
+    NumBytes = 1;
+  
+  if (Pool->NumSlabs > BitmapPoolTy::AddrArrSize)
+    Pool->Slabs->insert((void *)New);
+  else if (Pool->NumSlabs == BitmapPoolTy::AddrArrSize) {
+    // Create the hash_set
+    Pool->Slabs = new std::set<void *>;
+    Pool->Slabs->insert((void *)New);
+    for (unsigned i = 0; i < BitmapPoolTy::AddrArrSize; ++i)
+      Pool->Slabs->insert((void *)Pool->SlabAddressArray[i]);
+  }
+  else {
+    // Insert it in the array
+    Pool->SlabAddressArray[Pool->NumSlabs] = (void*) New;
+  }
+  Pool->NumSlabs++;
+
+  int Idx = New->allocateSingle();
+  assert(Idx == 0 && "New allocation didn't return zero'th node?");
+  if (logregs) {
+    fprintf(stderr, " poolalloc:967: canonical page at 0x%p from underlying allocator\n", (void*)New);
+  }
+  return New->getElementAddress(0, 0);
+}
+
+//
+// Function: poolstrdup()
+//
+// Description:
+//  Duplicate a string by allocating memory for a new string and copying the
+//  contents of the old string into the new string.
+//
+// Inputs:
+//  Pool - The pool in which the new string should reside.
+//  Node - The string which should be duplicated.
+//
+// Return value:
+//  0 - The duplication failed.
+//  Otherwise, a pointer to the duplicated string is returned.
+//
+void *
+__pa_bitmap_poolstrdup (BitmapPoolTy *Pool, void *Node) {
+  if (Node == 0) return 0;
+
+  unsigned int NumBytes = strlen((char*)Node) + 1;
+  void *New = __pa_bitmap_poolalloc (Pool, NumBytes);
+  if (New) {
+    memcpy(New, Node, NumBytes+1);
+  }
+  return New;
+}
+
+/////
+///
+/// Helper functions
+/// 
+/////
+
+// Function: poolallocarray()
+//
+// Description:
+//  This is a helper function used to implement poolalloc() when the number of
+//  nodes to allocate is not 1.
+//
+// Inputs:
+//  Pool - A pointer to the pool from which to allocate.
+//  Size - The number of nodes to allocate.
+//
+// FIXME: determine whether Size is bytes or number of nodes.
+//
+
+static void *
+poolallocarray(BitmapPoolTy* Pool, unsigned Size) {
+  assert(Pool && "Null pool pointer passed into poolallocarray!\n");
+  
+  // check to see if we need to allocate a single large array
+  if (Size > PoolSlab::getSlabSize(Pool)) {
+    if (logregs) {
+      fprintf(stderr, " poolallocarray:694: Size = %d, SlabSize = %d\n", Size, PoolSlab::getSlabSize(Pool));
+      fflush(stderr);
+    }
+    return PoolSlab::createSingleArray(Pool, Size);
+  }
+ 
+  PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+
+  // Loop through all of the slabs looking for one with an opening
+  for (; PS; PS = PS->Next) {
+    int Element = PS->allocateMultiple(Size);
+    if (Element != -1) {
+      //
+      // We allocated an element.  Check to see if this slab has been
+      // completely filled up.  If so, move it to the Ptr2 list.
+      //
+      if (PS->isFull()) {
+        PS->unlinkFromList();
+        PS->addToList((PoolSlab**)&Pool->Ptr2);
+      }
+      
+      return PS->getElementAddress(Element, Pool->NodeSize);
+    }
+  }
+  
+  PoolSlab *New = PoolSlab::create(Pool);
+  //  printf("new slab created %x \n", New);
+  if (Pool->NumSlabs > BitmapPoolTy::AddrArrSize)
+    Pool->Slabs->insert((void *)New);
+  else if (Pool->NumSlabs == BitmapPoolTy::AddrArrSize) {
+    // Create the hash_set
+    Pool->Slabs = new std::set<void *>;
+    Pool->Slabs->insert((void *)New);
+    for (unsigned i = 0; i < BitmapPoolTy::AddrArrSize; ++i)
+      Pool->Slabs->insert((void *)Pool->SlabAddressArray[i]);
+  }
+  else {
+    // Insert it in the array
+    Pool->SlabAddressArray[Pool->NumSlabs] = New;
+  }
+  
+  Pool->NumSlabs++;
+  
+  int Idx = New->allocateMultiple(Size);
+  assert(Idx == 0 && "New allocation didn't return zero'th node?");
+  
+  return New->getElementAddress(0, 0);
+}
+
+//
+// Function: poolfree()
+//
+// Description:
+//  Mark the object specified by the given pointer as free and available for
+//  allocation for new objects.
+//
+// Inputs:
+//  Pool - The pool to which the pointer should belong.
+//  Node - A pointer to the beginning of the object to free.  This pointer is
+//         allowed to be NULL.
+//
+// Notes:
+//  This routine should be resistent to several types of deallocation errors:
+//    o) Deallocating an object which does not exist within the pool.
+//    o) Deallocating an already-free object.
+//
+void
+__pa_bitmap_poolfree(BitmapPoolTy *Pool, void *Node) {
+  assert(Pool && "Null pool pointer passed in to poolfree!\n");
+  PoolSlab *PS;
+  int Idx;
+  
+  if (logregs) {
+    fprintf(stderr, "poolfree: 1368: Pool=%p, addr=%p\n", (void*) Pool, Node);
+    fflush (stderr);
+  }
+
+  //
+  // If the pointer is NULL, that is okay.  Just do nothing.
+  //
+  if (Node == 0) return;
+
+  // Canonical pointer for the pointer we're freeing
+  void * CanonNode = Node;
+
+  unsigned TheIndex = 0;
+  PS = SearchForContainingSlab(Pool, CanonNode, TheIndex);
+  Idx = TheIndex;
+
+  //
+  // If no slab can be found, then the pointer we were given is invalid.  Since
+  // we want to tolerate invalid frees, go ahead and return.
+  //
+  if (!PS) return;
+  assert (PS && "poolfree: No poolslab found for object!\n");
+  PS->freeElement(Idx);
+
+  //
+  // If we could not find the slab in which the node belongs, then we were
+  // passed an invalid pointer.  Simply ignore it.
+  //
+  if (!PS) return;
+  
+  // If PS was full, it must have been in list #2.  Unlink it and move it to
+  // list #1.
+  if (PS->isFull()) {
+    // Now that we found the node, we are about to free an element from it.
+    // This will make the slab no longer completely full, so we must move it to
+    // the other list!
+    PS->unlinkFromList(); // Remove it from the Ptr2 list.
+
+    //
+    // Do not re-use single array slabs.
+    //
+
+    if (!(PS->isSingleArray)) {
+      PoolSlab **InsertPosPtr = (PoolSlab**)&Pool->Ptr1;
+
+      // If the partially full list has an empty node sitting at the front of
+      // the list, insert right after it.
+      if ((*InsertPosPtr))
+        if ((*InsertPosPtr)->isEmpty())
+          InsertPosPtr = &(*InsertPosPtr)->Next;
+
+      PS->addToList(InsertPosPtr);     // Insert it now in the Ptr1 list.
+    }
+  }
+
+  // Ok, if this slab is empty, we unlink it from the of slabs and either move
+  // it to the head of the list, or free it, depending on whether or not there
+  // is already an empty slab at the head of the list.
+  if ((PS->isEmpty()) && (!(PS->isSingleArray))) {
+    PS->unlinkFromList();   // Unlink from the list of slabs...
+    
+    // If we can free this pool, check to see if there are any empty slabs at
+    // the start of this list.  If so, delete the FirstSlab!
+    PoolSlab *FirstSlab = (PoolSlab*)Pool->Ptr1;
+    if (0 && FirstSlab && FirstSlab->isEmpty()) {
+      // Here we choose to delete FirstSlab instead of the pool we just freed
+      // from because the pool we just freed from is more likely to be in the
+      // processor cache.
+    FirstSlab->unlinkFromList();
+    FirstSlab->destroy();
+    //  Pool->Slabs.erase((void *)FirstSlab);
+    }
+ 
+    // Link our slab onto the head of the list so that allocations will find it
+    // efficiently.    
+    PS->addToList((PoolSlab**)&Pool->Ptr1);
+  }
+
+  return; 
+}
+
+
+// SearchForContainingSlab - Do a brute force search through the list of
+// allocated slabs for the node in question.
+//
+static PoolSlab *
+SearchForContainingSlab(BitmapPoolTy *Pool, void *Node, unsigned &TheIndex) {
+  PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+  unsigned NodeSize = Pool->NodeSize;
+
+  // Search the partially allocated slab list for the slab that contains this
+  // node.
+  int Idx = -1;
+  if (PS) {               // Pool->Ptr1 could be null if Ptr2 isn't
+    for (; PS; PS = PS->Next) {
+      Idx = PS->containsElement(Node, NodeSize);
+      if (Idx != -1) break;
+    }
+  }
+
+  // If the partially allocated slab list doesn't contain it, maybe the
+  // completely allocated list does.
+  if (PS == 0) {
+    PS = (PoolSlab*)Pool->Ptr2;
+    assert(Idx == -1 && "Found node but don't have PS?");
+    
+    while (PS) {
+      assert(PS && "poolfree: node being free'd not found in allocation "
+             " pool specified!\n");
+      Idx = PS->containsElement(Node, NodeSize);
+      if (Idx != -1) break;
+      PS = PS->Next;
+    }
+  }
+  
+  // Otherwise, maybe its a block within LargeArrays
+  if(PS == 0) {
+    PS = (PoolSlab*)Pool->LargeArrays;
+    assert(Idx == -1  && "Found node but don't have PS?");
+    
+    while (PS) {
+      assert(PS && "poolfree: node being free'd not found in allocation "
+             " pool specified!\n");
+      Idx = PS->containsElement(Node, NodeSize);
+      if (Idx != -1) break;
+      PS = PS->Next;
+    }
+  }
+
+  TheIndex = Idx;
+  return PS;
+}
+
+//
+// Function: __pa_bitmap_poolcheck()
+//
+// Description:
+//  Determine whether the specified pointer is located within the specified
+//  pool and, if so, what its beginning address is.
+//
+void *
+__pa_bitmap_poolcheck (BitmapPoolTy * Pool, void * Node) {
+  //
+  // If there is no pool, do nothing.
+  //
+  if (!Pool)
+    return 0;
+
+  //
+  // Search for the object within the pool.
+  //
+  unsigned TheIndex;
+  if (PoolSlab * PS = SearchForContainingSlab (Pool, Node, TheIndex)) {
+    return PS->getElementAddress(TheIndex, Pool->NodeSize);
+  }
+
+  return 0;
+}
+
Index: runtime/libsc/BitmapPoolAllocator/PageManager.cpp
===================================================================
--- runtime/libsc/BitmapPoolAllocator/PageManager.cpp	(revision 0)
+++ runtime/libsc/BitmapPoolAllocator/PageManager.cpp	(revision 0)
@@ -0,0 +1,181 @@
+//===- PageManager.cpp - Implementation of the page allocator -------------===//
+// 
+//                          The SAFECode Compiler
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PageManager.h interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../include/PageManager.h"
+
+#ifndef _POSIX_MAPPED_FILES
+#define _POSIX_MAPPED_FILES
+#endif
+#include "../include/MallocAllocator.h"
+#include "../include/MMAPSupport.h"
+
+#include <unistd.h>
+
+#include <cassert>
+#include <cstdio>
+#include <iostream>
+#include <vector>
+#include <map>
+#include <utility>
+#include <cstring>
+
+#include <errno.h>
+
+namespace llvm {
+
+FreePagesListType FreePages;
+
+// Define this if we want to use memalign instead of mmap to get pages.
+// Empirically, this slows down the pool allocator a LOT.
+#define USE_MEMALIGN 0
+extern "C" {
+uintptr_t PageSize = 0;
+}
+
+static unsigned poolmemusage = 0;
+
+// Physical page size
+uintptr_t PPageSize;
+
+//
+// Function: InitializePageManager()
+//
+// Description:
+//  Perform nececessary initialization of the page manager code.  This must be
+//  called before any other function in this file is called.
+//
+void
+InitializePageManager() {
+  //
+  // Determine the physical page size.
+  //
+  if (!PPageSize) PPageSize = sysconf(_SC_PAGESIZE);
+
+  //
+  // Calculate the page size used by the run-time (which is a multiple of the
+  // machine's physical page size).
+  //
+  if (!PageSize) PageSize =  PageMultiplier * PPageSize;
+}
+
+#if !USE_MEMALIGN
+void *GetPages(unsigned NumPages) {
+#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(__x86_64__)
+  /* Linux and *BSD tend to have these flags named differently. */
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+# define MAP_ANONYMOUS MAP_ANON
+#endif /* defined(MAP_ANON) && !defined(MAP_ANONYMOUS) */
+#elif defined(sparc) || defined(__sparc__) || defined(__sparcv9)
+  /* nothing */
+#elif defined(__APPLE__)
+  /* On MacOS X, just use valloc */
+#else
+  std::cerr << "This architecture is not supported by the pool allocator!\n";
+  abort();
+#endif
+
+#if defined(__linux__)
+#define fd 0
+#else
+#define fd -1
+#endif
+  void *Addr;
+  //MMAP DOESNOT WORK !!!!!!!!
+  //  Addr = mmap(0, NumPages*PageSize, PROT_READ|PROT_WRITE,
+  //                 MAP_SHARED|MAP_ANONYMOUS, fd, 0);
+  //  void *pa = malloc(NumPages * PageSize);
+  //  assert(Addr != MAP_FAILED && "MMAP FAILED!");
+#if defined(__linux__)
+  Addr = mmap(0, NumPages * PageSize, PROT_READ|PROT_WRITE,
+                                      MAP_SHARED |MAP_ANONYMOUS, -1, 0);
+  if (Addr == MAP_FAILED) {
+     perror ("mmap:");
+     fflush (stdout);
+     fflush (stderr);
+     assert(0 && "valloc failed\n");
+  }
+#else
+#if POSIX_MEMALIGN
+   if (posix_memalign(&Addr, PageSize, NumPages*PageSize) != 0){
+     assert(0 && "memalign failed \n");
+   }
+#else
+   if ((Addr = valloc (NumPages*PageSize)) == 0){
+     perror ("valloc:");
+     fflush (stdout);
+     fflush (stderr);
+     assert(0 && "valloc failed \n");
+   } else {
+#if 0
+    fprintf (stderr, "valloc: Allocated %x\n", NumPages);
+    fflush (stderr);
+#endif
+   }
+#endif
+#endif
+  poolmemusage += NumPages * PageSize;
+
+  // Initialize the page to contain safe inital values
+  memset(Addr, initvalue, NumPages *PageSize);
+
+  return Addr;
+}
+#endif
+
+
+/// AllocatePage - This function returns a chunk of memory with size and
+/// alignment specified by PageSize.
+__attribute__((weak)) void * AllocatePage() {
+
+  FreePagesListType &FPL = FreePages;
+
+  if (!FPL.empty()) {
+    void *Result = FPL.back();
+      FPL.pop_back();
+      return Result;
+  }
+
+  // Allocate several pages, and put the extras on the freelist...
+  char *Ptr = (char*)GetPages(NumToAllocate);
+
+  // Place all but the first page into the page cache
+  for (unsigned i = 1; i != NumToAllocate; ++i) {
+    FPL.push_back (Ptr+i*PageSize);
+  }
+
+  return Ptr;
+}
+
+void *AllocateNPages(unsigned Num) {
+  if (Num <= 1) return AllocatePage();
+  return GetPages(Num);
+}
+
+/// FreePage - This function returns the specified page to the pagemanager for
+/// future allocation.
+void FreePage(void *Page) {
+  FreePagesListType &FPL = FreePages;
+  FPL.push_back(Page);
+  munmap(Page, 1);
+  /*
+  static const unsigned int THRESHOLD = 5;
+  if (FPL.size() >  THRESHOLD) {
+    //    printf( "pool allocator : reached a threshold \n");
+    //    exit(-1); 
+    munmap(Page, PageSize);
+    poolmemusage -= PageSize;
+  }
+  */
+}
+
+}
Index: runtime/libsc/BitmapPoolAllocator/PoolSlab.cpp
===================================================================
--- runtime/libsc/BitmapPoolAllocator/PoolSlab.cpp	(revision 0)
+++ runtime/libsc/BitmapPoolAllocator/PoolSlab.cpp	(revision 0)
@@ -0,0 +1,475 @@
+//===- PoolSlab.cpp - -----------------------------------------*- C++ -*---===//
+// 
+//                          The SAFECode Compiler
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements slabs of pool allocators.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PoolSlab.h"
+
+#include <cstdio>
+#include <cstdlib>
+
+namespace llvm {
+
+// create - Create a new (empty) slab and add it to the end of the Pools list.
+PoolSlab *
+PoolSlab::create(BitmapPoolTy *Pool) {
+  unsigned NodesPerSlab = getSlabSize(Pool);
+
+  unsigned Size = sizeof(PoolSlab) + 4*((NodesPerSlab+15)/16) +
+    Pool->NodeSize*getSlabSize(Pool);
+  assert(Size <= PageSize && "Trying to allocate a slab larger than a page!");
+  PoolSlab *PS = (PoolSlab*)AllocatePage();
+  assert(PS && "Allocating a page failed!");
+  PS->NumNodesInSlab = NodesPerSlab;
+  PS->isSingleArray = 0;  // Not a single array!
+  PS->FirstUnused = 0;    // Nothing allocated.
+  PS->UsedBegin   = 0;    // Nothing allocated.
+  PS->UsedEnd     = 0;    // Nothing allocated.
+  PS->allocated   = 0;    // No bytes allocated.
+
+  for (unsigned i = 0; i < PS->getSlabSize(); ++i)
+    {
+      PS->markNodeFree(i);
+      PS->clearStartBit(i);
+    }
+
+  // Add the slab to the list...
+	PS->addToList((PoolSlab**)&Pool->Ptr1);
+  //  printf(" creating a slab %x\n", PS);
+  return PS;
+}
+
+void *
+PoolSlab::createSingleArray(BitmapPoolTy *Pool, unsigned NumNodes) {
+  // FIXME: This wastes memory by allocating space for the NodeFlagsVector
+  unsigned NodesPerSlab = getSlabSize(Pool);
+  assert(NumNodes > NodesPerSlab && "No need to create a single array!");
+
+  unsigned NumPages = (NumNodes+NodesPerSlab-1)/NodesPerSlab;
+  PoolSlab *PS = (PoolSlab*)AllocateNPages(NumPages);
+
+  assert(PS && "poolalloc: Could not allocate memory!");
+
+  if (Pool->NumSlabs > BitmapPoolTy::AddrArrSize)
+    Pool->Slabs->insert((void*)PS);
+  else if (Pool->NumSlabs == BitmapPoolTy::AddrArrSize) {
+    // Create the hash_set
+    Pool->Slabs = new std::set<void *>;
+    Pool->Slabs->insert((void *)PS);
+    for (unsigned i = 0; i < BitmapPoolTy::AddrArrSize; ++i)
+      Pool->Slabs->insert((void *) Pool->SlabAddressArray[i]);
+  } else {
+    // Insert it in the array
+    Pool->SlabAddressArray[Pool->NumSlabs] = PS;
+  }
+  Pool->NumSlabs++;
+
+	PS->addToList((PoolSlab**)&Pool->LargeArrays);
+
+  PS->allocated   = 0xffffffff;    // No bytes allocated.
+  PS->isSingleArray = 1;
+  PS->NumNodesInSlab = NodesPerSlab;
+  PS->SizeOfSlab     = (NumPages * PageSize);
+  PS->FirstUnused = NumPages;
+  return PS->getElementAddress(0, 0);
+}
+
+void
+PoolSlab::destroy() {
+  if (isSingleArray)
+    for (unsigned NumPages = FirstUnused; NumPages != 1;--NumPages)
+      FreePage((char*)this + (NumPages-1)*PageSize);
+
+  FreePage(this);
+}
+
+// allocateSingle - Allocate a single element from this pool, returning -1 if
+// there is no space.
+int
+PoolSlab::allocateSingle() {
+  // If the slab is a single array, go on to the next slab.  Don't allocate
+  // single nodes in a SingleArray slab.
+  if (isSingleArray) return -1;
+
+  unsigned SlabSize = getSlabSize();
+
+  // Check to see if there are empty entries at the end of the slab...
+  if (UsedEnd < SlabSize) {
+    // Mark the returned entry used
+    unsigned short UE = UsedEnd;
+    markNodeAllocated(UE);
+    setStartBit(UE);
+    
+    // If we are allocating out the first unused field, bump its index also
+    if (FirstUnused == UE) {
+      FirstUnused++;
+    }
+    
+    // Updated the UsedBegin field if necessary
+    if (UsedBegin > UE) UsedBegin = UE;
+
+    // Return the entry, increment UsedEnd field.
+    ++UsedEnd;
+    assertOkay();
+    allocated += 1;
+    return UE;
+  }
+  
+  // If not, check to see if this node has a declared "FirstUnused" value that
+  // is less than the number of nodes allocated...
+  //
+  if (FirstUnused < SlabSize) {
+    // Successfully allocate out the first unused node
+    unsigned Idx = FirstUnused;
+    markNodeAllocated(Idx);
+    setStartBit(Idx);
+    
+    // Increment FirstUnused to point to the new first unused value...
+    // FIXME: this should be optimized
+    unsigned short FU = FirstUnused;
+    do {
+      ++FU;
+    } while ((FU != SlabSize) && (isNodeAllocated(FU)));
+    FirstUnused = FU;
+
+    // Updated the UsedBegin field if necessary
+    if (UsedBegin > Idx) UsedBegin = Idx;
+
+    assertOkay();
+    allocated += 1;
+    return Idx;
+  }
+  
+  assertOkay();
+  return -1;
+}
+
+//
+// Method: allocateMultiple()
+//
+// Description:
+//  Allocate multiple contiguous elements from this pool.
+//
+// Inputs:
+//  Size - The number of *nodes* to allocate from this slab.
+//
+// Return value:
+//  -1 - There is no space for an allocation of this size in the slab.
+//  -1 - An attempt was made to use this method on a single array slab.
+//  Otherwise, the index number of the first free node in the slab is returned.
+//
+int
+PoolSlab::allocateMultiple(unsigned Size) {
+  // Do not allocate small arrays in SingleArray slabs
+  if (isSingleArray) return -1;
+
+  // For small array allocation, check to see if there are empty entries at the
+  // end of the slab...
+  if (UsedEnd+Size <= getSlabSize()) {
+    // Mark the returned entry used and set the start bit
+    unsigned UE = UsedEnd;
+    setStartBit(UE);
+    for (unsigned i = UE; i != UE+Size; ++i)
+      markNodeAllocated(i);
+    
+    // If we are allocating out the first unused field, bump its index also
+    if (FirstUnused == UE)
+      FirstUnused += Size;
+
+    // Updated the UsedBegin field if necessary
+    if (UsedBegin > UE) UsedBegin = UE;
+
+    // Increment UsedEnd
+    UsedEnd += Size;
+
+    // Return the entry
+    assertOkay();
+    allocated += Size;
+    return UE;
+  }
+
+  //
+  // If not, check to see if this node has a declared "FirstUnused" value
+  // starting which Size nodes can be allocated
+  //
+  unsigned Idx = FirstUnused;
+  while (Idx+Size <= getSlabSize()) {
+    assert(!isNodeAllocated(Idx) && "FirstUsed is not accurate!");
+
+    // Check if there is a continuous array of Size nodes starting FirstUnused
+    unsigned LastUnused = Idx+1;
+    for (; (LastUnused != Idx+Size) && (!isNodeAllocated(LastUnused)); ++LastUnused)
+      /*empty*/;
+
+    // If we found an unused section of this pool which is large enough, USE IT!
+    if (LastUnused == Idx+Size) {
+      setStartBit(Idx);
+      // FIXME: this loop can be made more efficient!
+      for (unsigned i = Idx; i != Idx + Size; ++i)
+        markNodeAllocated(i);
+
+      // This should not be allocating on the end of the pool, so we don't need
+      // to bump the UsedEnd pointer.
+      assert(Idx != UsedEnd && "Shouldn't allocate at end of pool!");
+
+      // If we are allocating out the first unused field, bump its index also.
+      if (Idx == FirstUnused) {
+        unsigned SlabSize = getSlabSize();
+        unsigned i;
+        for (i = FirstUnused+Size; i < UsedEnd; ++i) {
+          if (!isNodeAllocated(i)) {
+            break;
+          }
+        }
+        FirstUnused = i;
+        if (isNodeAllocated(i))
+          FirstUnused = SlabSize;
+      }
+      
+      // Updated the UsedBegin field if necessary
+      if (UsedBegin > Idx) UsedBegin = Idx;
+
+      // Return the entry
+      assertOkay();
+      allocated += Size;
+      return Idx;
+    }
+
+    // Otherwise, try later in the pool.  Find the next unused entry.
+    Idx = LastUnused;
+    while (Idx+Size <= getSlabSize() && isNodeAllocated(Idx))
+      ++Idx;
+  }
+
+  assertOkay();
+  return -1;
+}
+
+// getSize
+unsigned PoolSlab::getSize(void *Ptr, unsigned ElementSize) {
+  if (isSingleArray) abort();
+  const void *FirstElement = getElementAddress(0, 0);
+  if (FirstElement <= Ptr) {
+    unsigned Delta = (char*)Ptr-(char*)FirstElement;
+    unsigned Index = Delta/ElementSize;
+    
+    if (Index < getSlabSize()) {
+      //we have the index now do something like free
+      assert(isStartOfAllocation(Index) &&
+             "poolrealloc: Attempt to realloc from the middle of allocated array\n");
+      unsigned short ElementEndIdx = Index + 1;
+      
+      // FIXME: This should use manual strength reduction to produce decent code.
+      unsigned short UE = UsedEnd;
+      while (ElementEndIdx != UE &&
+             !isStartOfAllocation(ElementEndIdx) && 
+             isNodeAllocated(ElementEndIdx)) {
+        ++ElementEndIdx;
+      }
+      return (ElementEndIdx - Index);
+    }
+  }
+  if (logregs)
+    {
+      fprintf(stderr, "PoolSlab::getSize failed!\n");
+      fflush(stderr);
+    }
+  abort();
+}
+
+
+//
+// Method: containsElement()
+//
+// Description:
+//  Return the element number of the specified address in this slab.  If the
+//  address is not in slab, return -1.
+//
+int
+PoolSlab::containsElement(void *Ptr, unsigned ElementSize) const {
+  const void *FirstElement = getElementAddress(0, 0);
+
+  //
+  // If the pointer is less than the first element of the slab, then it is
+  // not within the slab at all.
+  //
+  if (FirstElement <= Ptr) {
+
+    //
+    // Calculate the offet, in bytes, of the pointer from the beginning of the
+    // slab.
+    //
+    unsigned Delta = (char*)Ptr-(char*)FirstElement;
+
+    //
+    // If this array is a single array and the pointer is within the bounds of
+    // the slab, then simply return the offset of the pointer divided by the
+    // size of each element.
+    //
+    if (isSingleArray) {
+      if (Delta < SizeOfSlab) {
+        return Delta/ElementSize;
+      }
+    }
+
+    unsigned Index = Delta/ElementSize;
+    if (Index < getSlabSize()) {
+      if (Delta % ElementSize != 0) {
+        fprintf(stderr, "Freeing pointer into the middle of an element!\n");
+        fflush(stderr);
+        abort();
+      }
+      
+      return Index;
+    }
+  }
+
+  //
+  // The pointer is not within a slab.
+  //
+  return -1;
+}
+
+
+// freeElement - Free the single node, small array, or entire array indicated.
+void
+PoolSlab::freeElement(unsigned short ElementIdx) {
+  if (!isNodeAllocated(ElementIdx)) return;
+  //  assert(isNodeAllocated(ElementIdx) &&
+  //         "poolfree: Attempt to free node that is already freed\n");
+#if 0
+  assert(!isSingleArray && "Cannot free an element from a single array!");
+#else
+#if 0
+  if (isSingleArray) {
+    this->addToList((PoolSlab**)&Pool->FreeLargeArrays);
+    return;
+  }
+#endif
+#endif
+
+  // Mark this element as being free!
+  markNodeFree(ElementIdx);
+  --allocated;
+
+  // If this slab is not a SingleArray
+  assert(isStartOfAllocation(ElementIdx) &&
+         "poolfree: Attempt to free middle of allocated array\n");
+  
+  // Free the first cell
+  clearStartBit(ElementIdx);
+  markNodeFree(ElementIdx);
+  
+  // Free all nodes if this was a small array allocation.
+  unsigned short ElementEndIdx = ElementIdx + 1;
+
+  // FIXME: This should use manual strength reduction to produce decent code.
+  unsigned short UE = UsedEnd;
+  while (ElementEndIdx != UE &&
+         !isStartOfAllocation(ElementEndIdx) && 
+         isNodeAllocated(ElementEndIdx)) {
+    markNodeFree(ElementEndIdx);
+    --allocated;
+    ++ElementEndIdx;
+  }
+  
+  // Update the first free field if this node is below the free node line
+  if (ElementIdx < FirstUnused) FirstUnused = ElementIdx;
+
+  // Update the first used field if this node was the first used.
+  if (ElementIdx == UsedBegin) UsedBegin = ElementEndIdx;
+  
+  // If we are freeing the last element in a slab, shrink the UsedEnd marker
+  // down to the last used node.
+  if (ElementEndIdx == UE) {
+#if 0
+    printf("FU: %d, UB: %d, UE: %d  FREED: [%d-%d)",
+           FirstUnused, UsedBegin, UsedEnd, ElementIdx, ElementEndIdx);
+#endif
+
+    // If the user is freeing the slab entirely in-order, it's quite possible
+    // that all nodes are free in the slab.  If this is the case, simply reset
+    // our pointers.
+    if (UsedBegin == UE) {
+      FirstUnused = 0;
+      UsedBegin = 0;
+      UsedEnd = 0;
+      assertOkay();
+    } else if (FirstUnused == ElementIdx) {
+      // Freed the last node(s) in this slab.
+      FirstUnused = ElementIdx;
+      UsedEnd = ElementIdx;
+      assertOkay();
+    } else {
+      UsedEnd = lastNodeAllocated(ElementIdx);
+      if (FirstUnused > UsedEnd) FirstUnused = UsedEnd;
+      assertOkay();
+      assert(FirstUnused <= UsedEnd+1 &&
+             "FirstUnused field was out of date!");
+    }
+  }
+  assertOkay();
+}
+
+unsigned
+PoolSlab::lastNodeAllocated(unsigned ScanIdx) {
+  // Check the last few nodes in the current word of flags...
+  unsigned CurWord = ScanIdx/16;
+  unsigned short Flags = NodeFlagsVector[CurWord] & 0xFFFF;
+  if (Flags) {
+    // Mask off nodes above this one
+    Flags &= (1 << ((ScanIdx & 15)+1))-1;
+    if (Flags) {
+      // If there is still something in the flags vector, then there is a node
+      // allocated in this part.  The goto is a hack to get the uncommonly
+      // executed code away from the common code path.
+      //printf("A: ");
+      goto ContainsAllocatedNode;
+    }
+  }
+
+  // Ok, the top word doesn't contain anything, scan the whole flag words now.
+  --CurWord;
+  while (CurWord != ~0U) {
+    Flags = NodeFlagsVector[CurWord] & 0xFFFF;
+    if (Flags) {
+      // There must be a node allocated in this word!
+      //printf("B: ");
+      goto ContainsAllocatedNode;
+    }
+    CurWord--;
+  }
+  return 0;
+
+ ContainsAllocatedNode:
+  // Figure out exactly which node is allocated in this word now.  The node
+  // allocated is the one with the highest bit set in 'Flags'.
+  //
+  // This should use __builtin_clz to get the value, but this builtin is only
+  // available with GCC 3.4 and above.  :(
+  assert(Flags && "Should have allocated node!");
+  
+  unsigned short MSB;
+#if GCC3_4_EVENTUALLY
+  MSB = 16 - ::__builtin_clz(Flags);
+#else
+  for (MSB = 15; (Flags & (1U << MSB)) == 0; --MSB)
+    /*empty*/;
+#endif
+
+  assert((1U << MSB) & Flags);   // The bit should be set
+  assert((~(1U << MSB) & Flags) < Flags);// Removing it should make flag smaller
+  ScanIdx = CurWord*16 + MSB;
+  assert(isNodeAllocated(ScanIdx));
+  return (ScanIdx+1);
+}
+
+}
Index: runtime/libsc/BitmapPoolAllocator/Makefile
===================================================================
--- runtime/libsc/BitmapPoolAllocator/Makefile	(revision 0)
+++ runtime/libsc/BitmapPoolAllocator/Makefile	(revision 0)
@@ -0,0 +1,26 @@
+LEVEL = ../../..
+LIBRARYNAME=poolalloc_bitmap
+
+BYTECODE_LIBRARY=1
+
+#
+# Build shared libraries on all platforms except Cygwin and MingW (which do
+# not support them).
+#
+ifneq ($(OS),Cygwin)
+ifneq ($(OS),MingW)
+SHARED_LIBRARY=1
+endif
+endif
+
+ifeq ($(OS),Linux)
+CXX.Flags += -march=native
+else
+CXX.Flags += -march=nocona
+endif
+
+CXX.Flags += -fno-threadsafe-statics
+include $(LEVEL)/Makefile.common
+
+# Always build optimized and debug versions
+all:: $(LIBNAME_OBJO) $(LIBNAME_OBJG)
Index: runtime/libsc/DebugRuntime/ExactCheck.cpp
===================================================================
--- runtime/libsc/DebugRuntime/ExactCheck.cpp	(revision 0)
+++ runtime/libsc/DebugRuntime/ExactCheck.cpp	(revision 0)
@@ -0,0 +1,228 @@
+/*===- ExactCheck.cpp - Implementation of exactcheck functions ------------===*/
+/*                                                                            */
+/*                          The SAFECode Compiler                             */
+/*                                                                            */
+/* This file was developed by the LLVM research group and is distributed      */
+/* under the University of Illinois Open Source License. See LICENSE.TXT for  */
+/* details.                                                                   */
+/*                                                                            */
+/*===----------------------------------------------------------------------===*/
+/*                                                                            */
+/* This file implements the exactcheck family of functions.                   */
+/*                                                                            */
+/*===----------------------------------------------------------------------===*/
+
+#include "DebugReport.h"
+#include "ConfigData.h"
+
+#include "../include/BitmapAllocator.h"
+
+#include <stdint.h>
+
+#include <cstdio>
+
+extern FILE * ReportLog;
+
+using namespace llvm;
+
+static void *
+exactcheck_check (const void * ObjStart, const void * ObjEnd,
+                  const void * Dest, const char * SourceFile,
+                  unsigned int lineno) __attribute__((noinline));
+/*
+ * Function: exactcheck2()
+ *
+ * Description:
+ *  Determine whether a pointer is within the specified bounds of an object.
+ *
+ * Inputs:
+ *  base   - The address of the first byte of a memory object.
+ *  result - The pointer that is being checked.
+ *  size   - The size of the object in bytes.
+ *
+ * Return value:
+ *  If there is no bounds check violation, the result pointer is returned.
+ *  Otherwise, depending upon the configuration of the run-time, either an
+ *  error is returned or a rewritten Out-of-Bounds (OOB) pointer is returned.
+ */
+void *
+exactcheck2 (const char *base, const char *result, unsigned size) {
+  /*
+   * If the pointer is within the object, the check passes.  Return the checked
+   * pointer.
+   */
+  if ((result >= base) && (result < (base + size))) {
+    return (void*)result;
+  }
+
+  return exactcheck_check (base, base + size-1, result, NULL, 0);
+}
+
+/*
+ * Function: exactcheck2_debug()
+ *
+ * Description:
+ *  This function is identical to exactcheck2(), but the caller provides more
+ *  source level information about the run-time check for error reporting if
+ *  the check fails.
+ *
+ * Inputs:
+ *  base   - The address of the first byte of a memory object.
+ *  result - The pointer that is being checked.
+ *  size   - The size of the object in bytes.
+ *
+ * Return value:
+ *  If there is no bounds check violation, the result pointer is returned.
+ *  This forces the call to exactcheck() to be considered live (previous
+ *  optimizations dead-code eliminated it).
+ */
+void *
+exactcheck2_debug (const char *base,
+                   const char *result,
+                   unsigned size,
+                   unsigned tag,
+                   const char * SourceFile,
+                   unsigned lineno) {
+  /*
+   * If the pointer is within the object, the check passes.  Return the checked
+   * pointer.
+   */
+  if ((result >= base) && (result < (base + size))) {
+    return (void*) result;
+  }
+
+  return exactcheck_check (base, base + size - 1, result, SourceFile, lineno);
+}
+
+/*
+ * Function: exactcheck_check()
+ *
+ * Description:
+ *  This is the slow path for an exactcheck.  It handles pointer rewriting
+ *  and error reporting when an exactcheck fails.
+ *
+ * Inputs:
+ *  ObjStart - The address of the first valid byte of the object.
+ *  ObjEnd   - The address of the last valid byte of the object.
+ *  Dest     - The result pointer of the indexing operation (the GEP).
+ *  SourceFile - The name of the file in which the check occurs.
+ *  lineno     - The line number within the file in which the check occurs.
+ */
+void *
+exactcheck_check (const void * ObjStart,
+                  const void * ObjEnd,
+                  const void * Dest,
+                  const char * SourceFile,
+                  unsigned int lineno) {
+
+  /*
+   * First, we know that the pointer is out of bounds.  If we indexed off the
+   * beginning or end of a valid object, determine if we can rewrite the
+   * pointer into an OOB pointer.  Whether we can or not depends upon the
+   * SAFECode configuration.
+   */
+  if ((!(ConfigData.StrictIndexing)) ||
+      (((char *) Dest) == (((char *)ObjEnd)+1))) {
+    void * ptr = rewrite_ptr (0, Dest, ObjStart, ObjEnd, SourceFile, lineno);
+    if (logregs) {
+      fprintf (ReportLog,
+               "exactcheck: rewrite(1): %p %p %p at pc=%p to %p: %s %d\n",
+               ObjStart, ObjEnd, Dest, (void*)__builtin_return_address(0), ptr,
+               SourceFile, lineno);
+      fflush (ReportLog);
+    }
+    return ptr;
+  } else {
+    //
+    // Determine if this is a rewrite pointer that is being indexed.
+    //
+    if ((logregs) && (((uintptr_t)Dest > (uintptr_t)0xc0000000))) {
+      fprintf (stderr, "Was a rewrite: %p\n", Dest);
+      fflush (stderr);
+    }
+
+    OutOfBoundsViolation v;
+    v.type = ViolationInfo::FAULT_OUT_OF_BOUNDS,
+      v.faultPC = __builtin_return_address(0),
+      v.faultPtr = Dest,
+      v.PoolHandle = 0,
+      v.dbgMetaData = NULL,
+      v.SourceFile = SourceFile,
+      v.objStart = ObjStart,
+      v.objLen = (unsigned)((const char*)ObjEnd - (const char*)ObjStart + 1),
+      v.lineNo = lineno;
+    
+    ReportMemoryViolation(&v);
+  }
+
+  return const_cast<void*>(Dest);
+}
+
+#if 0
+/// UNUSED CODE
+
+/*
+ * Function: exactcheck()
+ *
+ * Description:
+ *  Determine whether the index is within the specified bounds.
+ *
+ * Inputs:
+ *  a      - The index given as an integer.
+ *  b      - The index of one past the end of the array.
+ *  result - The pointer that is being checked.
+ *
+ * Return value:
+ *  If there is no bounds check violation, the result pointer is returned.
+ *  This forces the call to exactcheck() to be considered live (previous
+ *  optimizations dead-code eliminated it).
+ */
+void *
+exactcheck (int a, int b, void * result) {
+  if ((0 > a) || (a >= b)) {
+    ReportExactCheck ((unsigned)0xbeefdeed,
+                      (uintptr_t)result,
+                      (uintptr_t)__builtin_return_address(0),
+                      (unsigned)a,
+                      (unsigned)0,
+                      "<Unknown>",
+                      0);
+#if 0
+    poolcheckfail ("exact check failed", (a), (void*)__builtin_return_address(0));
+    poolcheckfail ("exact check failed", (b), (void*)__builtin_return_address(0));
+#endif
+  }
+  return result;
+}
+
+
+void *
+exactcheck3(signed char *base, signed char *result, signed char * end) {
+  if ((result < base) || (result > end )) {
+    ReportExactCheck ((unsigned)0xbeefbeef,
+                      (uintptr_t)result,
+                      (uintptr_t)__builtin_return_address(0),
+                      (uintptr_t)base,
+                      (unsigned)(end-base),
+                      "<Unknown>",
+                      0);
+  }
+  return result;
+}
+
+
+void *
+exactcheck2a (signed char *base, signed char *result, unsigned size) {
+  if (result >= base + size ) {
+    ReportExactCheck ((unsigned)0xbeefdeed,
+                      (uintptr_t)result,
+                      (uintptr_t)__builtin_return_address(0),
+                      (uintptr_t)base,
+                      (unsigned)size,
+                      "<Unknown>",
+                      0);
+  }
+  return result;
+}
+
+#endif
Index: runtime/libsc/DebugRuntime/RuntimeChecks.cpp
===================================================================
--- runtime/libsc/DebugRuntime/RuntimeChecks.cpp	(revision 0)
+++ runtime/libsc/DebugRuntime/RuntimeChecks.cpp	(revision 0)
@@ -0,0 +1,874 @@
+//===- PoolAllocatorBitMask.cpp - Implementation of poolallocator runtime -===//
+// 
+//                          The SAFECode Compiler
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements various runtime checks used by SAFECode.
+//
+//===----------------------------------------------------------------------===//
+// NOTES:
+//  1) Some of the bounds checking code may appear strange.  The reason is that
+//     it is manually inlined to squeeze out some more performance.  Please
+//     don't change it.
+//
+//  2) This run-time performs MMU re-mapping of pages to perform dangling
+//     pointer detection.  A "shadow" address is the address of a memory block
+//     that has been remapped to a new virtal address; the shadow address is
+//     returned to the caller on allocation and is unmapped on deallocation.
+//     A "canonical" address is the virtual address of memory as it is mapped
+//     in the pool slabs; the canonical address is remapped to different shadow
+//     addresses each time that particular piece of memory is allocated.
+//
+//     In normal operation, the shadow address and canonical address are
+//     identical.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugReport.h"
+#include "PoolAllocator.h"
+#include "PageManager.h"
+#include "ConfigData.h"
+#include "RewritePtr.h"
+
+#include "../include/DebugRuntime.h"
+
+#include <map>
+#include <cstdarg>
+#include <cstdio>
+#include <cassert>
+
+#define TAG unsigned tag
+
+extern FILE * ReportLog;
+
+using namespace llvm;
+
+static inline unsigned char
+isInCache (DebugPoolTy * Pool, void * p) {
+  if ((Pool->objectCache[0].lower <= p) && (p <= Pool->objectCache[0].upper))
+    return 0;
+
+  if ((Pool->objectCache[1].lower <= p) && (p <= Pool->objectCache[1].upper))
+    return 1;
+
+  return 2;
+}
+
+static inline void
+updateCache (DebugPoolTy * Pool, void * Start, void * End) {
+  Pool->objectCache[Pool->cacheIndex].lower = Start;
+  Pool->objectCache[Pool->cacheIndex].upper = End;
+  Pool->cacheIndex = (Pool->cacheIndex) ? 0 : 1;
+  return;
+}
+
+//
+// Function: _barebone_poolcheck()
+//
+// Description:
+//  Perform an accurate load/store check for the given pointer.  This function
+//  encapsulates the logic necessary to do the check.
+//
+// Return value:
+//  true  - The pointer was found within a valid object within the pool.
+//  false - The pointer was not found within a valid object within the pool.
+//
+static inline bool
+_barebone_poolcheck (DebugPoolTy * Pool, void * Node) {
+  void * S, * end;
+
+  //
+  // If the pool handle is NULL, return successful.
+  //
+  if (!Pool) return false;
+
+  //
+  // First check the cache of objects to see if the pointer is in there.
+  //
+  unsigned char index = isInCache (Pool, Node);
+  if (index < 2) {
+    return true;
+  }
+
+  //
+  // Look through the splay trees for an object in which the pointer points.
+  //
+  bool fs = Pool->Objects.find(Node, S, end);
+  if ((fs) && (S <= Node) && (Node <= end)) {
+    updateCache (Pool, S, end);
+    return true;
+  }
+
+  //
+  // This may be a singleton object, so search for it within the pool slabs
+  // itself.
+  //
+#if 1
+  if (void * start = __pa_bitmap_poolcheck (Pool, Node)) {
+    end = (unsigned char *) start + Pool->NodeSize - 1;
+    updateCache (Pool, start, end);
+    return true;
+  }
+#endif
+
+  //
+  // The node is not found or is not within bounds; fail!
+  //
+  return false;
+}
+
+//
+// Function: poolcheck_debug()
+//
+// Description:
+//  This function performs a load/store check.  It ensures that the given
+//  pointer points into a valid memory object.
+//
+void
+poolcheck_debug (DebugPoolTy *Pool,
+                 void *Node,
+                 TAG,
+                 const char * SourceFilep,
+                 unsigned lineno) {
+
+  //
+  // Check to see if the pointer points to an object within the pool.  If it
+  // does, the check succeeds, so just return to the caller.
+  //
+  if (_barebone_poolcheck (Pool, Node))
+    return;
+
+  //
+  // Look for the object within the splay tree of external objects.
+  //
+  int fs = 0;
+  void * start, *end;
+  fs = ExternalObjects->find (Node, start, end);
+  if ((fs) && (start <= Node) && (Node <= end)) {
+    return;
+  }
+
+  //
+  // If it's a rewrite pointer, convert it back into its original value so
+  // that we can print the real faulting address.
+  //
+  if (isRewritePtr (Node)) {
+    Node = pchk_getActualValue (Pool, Node);
+  }
+
+  //
+  // If dangling pointer detection is enabled, see if the pointer points within
+  // a freed memory object.  If so, this is a dangling pointer error.
+  // Otherwise, it is just a regular load/store error.
+  //
+  DebugViolationInfo v;
+  v.type = ViolationInfo::FAULT_LOAD_STORE,
+    v.faultPC = __builtin_return_address(0),
+    v.faultPtr = Node,
+    v.SourceFile = SourceFilep,
+    v.lineNo = lineno,
+    v.PoolHandle = Pool;
+
+  ReportMemoryViolation(&v);
+  return;
+}
+
+
+//
+// Function: poolcheckalign_debug()
+//
+// Description:
+//  Identical to poolcheckalign() but with additional debug info parameters.
+//
+// Inputs:
+//  Pool   - The pool in which the pointer should be found.
+//  Node   - The pointer to check.
+//  Offset - The offset, in bytes, that the pointer should be to the beginning
+//           of objects found in the pool.
+//
+// FIXME:
+//  For now, this does nothing, but it should, in fact, do a run-time check.
+//
+void
+poolcheckalign_debug (DebugPoolTy *Pool, void *Node, unsigned Offset, TAG, const char * SourceFile, unsigned lineno) {
+  //
+  // Let null pointers go if the alignment is zero; such pointers are aligned.
+  //
+  if ((Node == 0) && (Offset == 0))
+    return;
+
+  //
+  // If no pool was specified, return.
+  //
+  if (!Pool) return;
+
+  //
+  // First check the cache of objects to see if the pointer is in there.
+  //
+  void * S = 0;
+  void * end = 0;
+  bool found = false;
+  unsigned char index = isInCache (Pool, Node);
+  if (index < 2) {
+    S   = Pool->objectCache[index].lower;
+    end = Pool->objectCache[index].upper;
+    found = true;
+  }
+
+  //
+  // Look for the object in the splay of regular objects.
+  //
+  if (!found)
+    found = Pool->Objects.find (Node, S, end);
+
+  //
+  // If we can't find the object in the splay tree, try to find it in the pool
+  // itself.
+  //
+  if (!found) {
+#if 1
+    if (void * start = __pa_bitmap_poolcheck (Pool, Node)) {
+      S = start;
+      end = (unsigned char *)start + Pool->NodeSize - 1;
+      found = true;
+    }
+#endif
+  }
+
+  //
+  // Determine whether the alignment of the object is correct.  Note that Node
+  // may be pointing to an array of objects, so we need to take the offset of
+  // the pointer from the beginning of the object modulo the size of a single
+  // array element.  In this run-time, the size of a single element is stored
+  // within the pool descriptor.
+  //
+  if (found) {
+    unsigned char * Nodep = (unsigned char *) Node;
+    unsigned char * Sp = (unsigned char *) S;
+    unsigned Alignment = ((Nodep - Sp) % Pool->NodeSize);
+    if (Alignment == Offset) {
+      return;
+    }
+  }
+
+  //
+  // The object has not been found.  Provide an error.
+  //
+  if (logregs) {
+    fprintf (stderr, "Violation(A): %p: %p %d %d\n", (void *) Pool, Node, Offset, Pool->NodeSize);
+    fflush (stderr);
+  }
+
+  unsigned char * Sp = (unsigned char *) S;
+  unsigned char * endp = (unsigned char *) end;
+
+  AlignmentViolation v;
+  v.type = ViolationInfo::FAULT_ALIGN,
+    v.faultPC = __builtin_return_address(0),
+    v.faultPtr = Node,
+    v.PoolHandle = Pool,
+    v.dbgMetaData = 0,
+    v.SourceFile = SourceFile,
+    v.lineNo = lineno,
+    v.objStart = (found ? Sp : 0),
+    v.objLen = (found ? (endp - Sp) + 1: 0);
+    v.alignment = Offset;
+
+  ReportMemoryViolation(&v);
+}
+
+void
+poolcheckui_debug (DebugPoolTy *Pool,
+                   void *Node,
+                   TAG,
+                   const char * SourceFilep,
+                   unsigned lineno) {
+
+  if (_barebone_poolcheck (Pool, Node))
+    return;
+
+  //
+  // Look for the object within the splay tree of external objects.
+  // Always look in these splay tree because some objects (namely argv strings)
+  // are stored in this splay tree.
+  //
+  int fs = 0;
+  void * S, *end = 0;
+	if (1) {
+		S = Node;
+		fs = ExternalObjects->find (Node, S, end);
+		if ((fs) && (S <= Node) && (Node <= end)) {
+			return;
+		}
+	}
+
+  //
+  // The node is not found or is not within bounds.  Report a warning but keep
+  // going.
+  //
+	if (logregs) {
+    fprintf (stderr, "PoolcheckUI failed(%p:%x): %p %p from %p\n", 
+        (void*)Pool, fs, (void*)Node, end, __builtin_return_address(0));
+    fflush (stderr);
+  }
+
+  //
+  // Report a potential (but not certain) load/store violation.
+  //
+  DebugViolationInfo v;
+  v.type = ViolationInfo::WARN_LOAD_STORE,
+    v.faultPC = __builtin_return_address(0),
+    v.faultPtr = Node,
+    v.SourceFile = SourceFilep,
+    v.lineNo = lineno,
+    v.PoolHandle = Pool;
+
+  ReportMemoryViolation(&v);
+
+  return;
+}
+
+//
+// Function: boundscheck_lookup()
+//
+// Description:
+//  Perform the lookup for a bounds check.
+//
+// Inputs:
+//  Source - The pointer to look up within the set of valid objects.
+//
+// Outputs:
+//  Source - If the object is found within the pool, this is the address of the
+//           first valid byte of the object.
+//
+//  End    - If the object is found within the pool, this is the address of the
+//           last valid byte of the object.
+//
+// Return value:
+//  true  - The object was found in the pool.
+//  false - The object was not found in the pool.
+//
+static bool 
+boundscheck_lookup (DebugPoolTy * Pool, void * & Source, void * & End ) {
+  //
+  // If there is a pool, then search for the object within the pool and return
+  // its bounds.
+  //
+  if (Pool) {
+    //
+    // First check the cache of objects to see if the pointer is in there.
+    //
+    unsigned char index = isInCache (Pool, Source);
+    if (index < 2) {
+      Source = Pool->objectCache[index].lower;
+      End    = Pool->objectCache[index].upper;
+      return true;
+    }
+
+    //
+    // Search the splay tree.  If we find the object, add it to the cache.
+    //
+    if (Pool->Objects.find(Source, Source, End)) {
+      updateCache (Pool, Source, End);
+      return true;
+    }
+
+    //
+    // Perhaps we are indexing on a singleton object.  Do a poolcheck to
+    // get the object bounds and recheck the pointer.
+    //
+#if 1
+    if (void * start = __pa_bitmap_poolcheck (Pool, Source)) {
+      Source = start;
+      End = (unsigned char *)start + Pool->NodeSize - 1;
+      updateCache (Pool, Source, End);
+      return true;
+    }
+#endif
+  }
+
+  //
+  // No pool was given, so we cannot find the object.  Let the run-time use the
+  // slow path to search for externally allocated objects, argv pointers, and
+  // the like.
+  //
+  return false;
+}
+
+//
+// Function: boundscheck_check()
+//
+// Description:
+//  This is the slow path for a boundscheck() and boundcheckui() calls.
+//
+// Inputs:
+//  ObjStart - The address of the first valid byte of the object.
+//  ObjEnd   - The address of the last valid byte of the object.
+//  Pool     - The pool in which the pointer belong.
+//  Source   - The source pointer used in the indexing operation (the GEP).
+//  Dest     - The result pointer of the indexing operation (the GEP).
+//  CanFail  - Flags whether the check can fail (for complete DSNodes).
+//
+// Note:
+//  If ObjLen is zero, then the lookup says that Source was not found within
+//  any valid object.
+//
+static void *
+boundscheck_check (bool found, void * ObjStart, void * ObjEnd,
+                   DebugPoolTy * Pool,
+                   void * Source, void * Dest, bool CanFail,
+                   const char * SourceFile, unsigned int lineno) {
+  //
+  // Determine if this is a rewrite pointer that is being indexed.  If so,
+  // compute the original value, re-do the indexing operation, and rewrite the
+  // value back.
+  //
+  if (isRewritePtr (Source)) {
+    //
+    // Get the real pointer value (which is outside the bounds of a valid
+    // object).
+    //
+    void * RealSrc = pchk_getActualValue (Pool, Source);
+
+    //
+    // Compute the real result pointer (the value the GEP would really have on
+    // the original pointer value).
+    //
+    Dest = (void *)((intptr_t) RealSrc + ((intptr_t) Dest - (intptr_t) Source));
+
+    //
+    // Retrieve the original bounds of the object.
+    //
+    getOOBObject (Source, ObjStart, ObjEnd);
+
+    //
+    // Redo the bounds check.  If it succeeds, return the real value.
+    // Otherwise, just continue on with the rest of the failed bounds check
+    // processing as before.
+    //
+    if (__builtin_expect (((ObjStart <= Dest) && ((Dest <= ObjEnd))), 1)) {
+      if (logregs) {
+        fprintf (stderr, "unrewrite(1): (0x%p) -> (0x%p, 0x%p) \n", Source, RealSrc, Dest);
+        fflush (stderr);
+      }
+      return Dest;
+    }
+
+    //
+    // Pretend this was an index off of the original out of bounds pointer
+    // value and continue processing
+    //
+    if (logregs) {
+      fprintf (stderr, "unrewrite(2): %p -> %p, Dest: %p, Obj: %p - %p\n", Source, RealSrc, Dest, ObjStart, ObjEnd);
+      fflush (stderr);
+    }
+
+    found = true;
+    Source = RealSrc;
+  }
+
+  //
+  // Now, we know that the pointer is out of bounds.  If we indexed off the
+  // beginning or end of a valid object, determine if we can rewrite the
+  // pointer into an OOB pointer.  Whether we can or not depends upon the
+  // SAFECode configuration.
+  //
+  if (found) {
+    if ((ConfigData.StrictIndexing == false) ||
+        (((char *) Dest) == (((char *)ObjEnd)+1))) {
+      void * ptr = rewrite_ptr (Pool, Dest, ObjStart, ObjEnd, SourceFile, lineno);
+      if (logregs) {
+        fprintf (ReportLog, "boundscheck: rewrite(1): %p %p %p %p at pc=%p to %p at %s (%d)\n",
+                 ObjStart, ObjEnd, Source, Dest, (void*)__builtin_return_address(0), ptr, SourceFile, lineno);
+        fflush (ReportLog);
+      }
+      return ptr;
+    } else {
+      intptr_t allocPC = 0;
+      unsigned allocID = 0;
+      unsigned char * allocSF = (unsigned char *) "<Unknown>";
+      unsigned allocLN = 0;
+      PDebugMetaData debugmetadataptr = NULL;
+      void * S , * end;
+      if (dummyPool.DPTree.find(ObjStart, S, end, debugmetadataptr)) {
+        allocPC = ((intptr_t) (debugmetadataptr->allocPC)) - 5;
+        allocID  = debugmetadataptr->allocID;
+        allocSF  = (unsigned char *) debugmetadataptr->SourceFile;
+        allocLN  = debugmetadataptr->lineno;
+      }
+
+      OutOfBoundsViolation v;
+      v.type = ViolationInfo::FAULT_OUT_OF_BOUNDS,
+        v.faultPC = __builtin_return_address(0),
+        v.faultPtr = Dest,
+        v.dbgMetaData = debugmetadataptr,
+				v.PoolHandle = Pool, 
+        v.SourceFile = SourceFile,
+        v.lineNo = lineno,
+        v.objStart = ObjStart,
+        v.objLen = (unsigned)((char*) ObjEnd - (char*)(ObjStart)) + 1;
+
+      ReportMemoryViolation(&v);
+      return Dest;
+    }
+  }
+
+  /*
+   * Allow pointers to the first page in memory provided that they remain
+   * within that page.  Loads and stores using such pointers will fault.  This
+   * allows indexing of NULL pointers without error.
+   */
+  if ((((unsigned char *)0) <= Source) && (Source < (unsigned char *)(4096))) {
+    if ((((unsigned char *)0) <= Dest) && (Dest < (unsigned char *)(4096))) {
+      if (logregs) {
+        fprintf (ReportLog, "boundscheck: NULL Index: %x %x %p %p at pc=%p at %s (%d)\n",
+                 0, 4096, (void*)Source, (void*)Dest, (void*)__builtin_return_address(0), SourceFile, lineno);
+        fflush (ReportLog);
+      }
+      return Dest;
+    } else {
+      if ((ConfigData.StrictIndexing == false) ||
+          (((uintptr_t) Dest) == 4096)) {
+        if (logregs) {
+          fprintf (ReportLog, "boundscheck: rewrite(3): %x %x %p %p at pc=%p at %s (%d)\n",
+                   0, 4096, (void*)Source, (void*)Dest, (void*)__builtin_return_address(0), SourceFile, lineno);
+          fflush (ReportLog);
+        }
+        return rewrite_ptr (Pool,
+                            Dest,
+                            (void *)0,
+                            (void *)4096,
+                            SourceFile,
+                            lineno);
+      } else {
+        OutOfBoundsViolation v;
+        v.type = ViolationInfo::FAULT_OUT_OF_BOUNDS,
+          v.faultPC = __builtin_return_address(0),
+          v.faultPtr = Dest,
+          v.dbgMetaData = NULL,
+				  v.PoolHandle = Pool, 
+          v.SourceFile = NULL,
+          v.lineNo = 0,
+          v.objStart = 0,
+          v.objLen = 4096;
+
+        ReportMemoryViolation(&v);
+      }
+    }
+  }
+
+  //
+  // Attempt to look for the object in the external object splay tree.
+  // Do this even if we're not tracking external allocations because a few
+  // other objects without associated pools (e.g., argv pointers) may be
+  // registered in here.
+  //
+  if (1) {
+    void * S, * end;
+    bool fs = ExternalObjects->find(Source, S, end);
+    if (fs) {
+      if ((S <= Dest) && (Dest <= end)) {
+        return Dest;
+      } else {
+        if ((ConfigData.StrictIndexing == false) ||
+            (((char *) Dest) == (((char *)end)+1))) {
+          void * ptr = rewrite_ptr (Pool, Dest, S, end, SourceFile, lineno);
+          if (logregs)
+            fprintf (ReportLog,
+                     "boundscheck: rewrite(2): %p %p %p %p at pc=%p to %p at %s (%d)\n",
+                     S, end, Source, Dest, (void*)__builtin_return_address(0),
+                     ptr, SourceFile, lineno);
+          fflush (ReportLog);
+          return ptr;
+        }
+        
+        OutOfBoundsViolation v;
+        v.type = ViolationInfo::FAULT_OUT_OF_BOUNDS,
+          v.faultPC = __builtin_return_address(0),
+          v.faultPtr = Dest,
+          v.dbgMetaData = NULL,
+				  v.PoolHandle = Pool, 
+          v.SourceFile = SourceFile,
+          v.lineNo = lineno,
+          v.objStart = ObjStart,
+          v.objLen = (unsigned)((char*) end - (char*)(S)) + 1;
+
+        ReportMemoryViolation(&v);
+      }
+    }
+  }
+
+  //
+  // We cannot find the object.  Continue execution.
+  //
+  if (CanFail) {
+    OutOfBoundsViolation v;
+    v.type = ViolationInfo::FAULT_OUT_OF_BOUNDS,
+      v.faultPC = __builtin_return_address(0),
+      v.faultPtr = Dest,
+			v.PoolHandle = Pool, 
+      v.dbgMetaData = NULL,
+      v.SourceFile = SourceFile,
+      v.lineNo = lineno,
+      v.objStart = 0,
+      v.objLen = 0;
+    
+    ReportMemoryViolation(&v);
+
+  }
+
+  //
+  // Perform one last-ditch check for incomplete nodes.  It may be possible
+  // that we're doing a GEP off a pointer into a freed object.  If dangling
+  // pointer detection is enabled, we can determine if the source pointer
+  // was freed and reject the indexing operation.
+  //
+  PDebugMetaData debugmetadataptr = NULL;
+  if ((ConfigData.RemapObjects) &&
+      (dummyPool.DPTree.find (Source, ObjStart, ObjEnd, debugmetadataptr))) {
+    //
+    // If the indexing operation stays within the bounds of a freed object,
+    // then don't flag an error.  Dereferences of the pointer will flag an
+    // error.
+    //
+    if (__builtin_expect (((ObjStart <= Dest) && ((Dest <= ObjEnd))), 1)) {
+      return Dest;
+    }
+
+    //
+    // Otherwise, do what we always do: either rewrite the pointer or generate
+    // an array indexing error report.
+    //
+    if ((ConfigData.StrictIndexing == false) ||
+        (((char *) Dest) == (((char *)ObjEnd)+1))) {
+      void * ptr = rewrite_ptr (Pool, Dest, ObjStart, ObjEnd, SourceFile, lineno);
+      if (logregs) {
+        fprintf (ReportLog, "boundscheck: rewrite(4): %p %p %p %p at pc=%p to %p at %s (%d)\n",
+                 ObjStart, ObjEnd, Source, Dest, (void*)__builtin_return_address(0), ptr, SourceFile, lineno);
+        fflush (ReportLog);
+      }
+      return ptr;
+    } else {
+      intptr_t allocPC = 0;
+      unsigned allocID = 0;
+      unsigned char * allocSF = (unsigned char *) "<Unknown>";
+      unsigned allocLN = 0;
+      allocPC = ((intptr_t) (debugmetadataptr->allocPC)) - 5;
+      allocID  = debugmetadataptr->allocID;
+      allocSF  = (unsigned char *) debugmetadataptr->SourceFile;
+      allocLN  = debugmetadataptr->lineno;
+
+      OutOfBoundsViolation v;
+      v.type = ViolationInfo::FAULT_OUT_OF_BOUNDS,
+        v.faultPC = __builtin_return_address(0),
+        v.faultPtr = Dest,
+        v.dbgMetaData = debugmetadataptr,
+				v.PoolHandle = Pool, 
+        v.SourceFile = SourceFile,
+        v.lineNo = lineno,
+        v.objStart = ObjStart,
+        v.objLen = (unsigned)((char*) ObjEnd - (char*)(ObjStart)) + 1;
+
+      ReportMemoryViolation(&v);
+      return Dest;
+    }
+  }
+  return Dest;
+}
+
+//
+// Function: boundscheck_debug()
+//
+// Description:
+//  Identical to boundscheck() except that it takes additional debug info
+//  parameters.
+//
+// FIXME: this function is marked as noinline due to LLVM bug 4562
+// http://llvm.org/bugs/show_bug.cgi?id=4562
+//
+// the attribute should be taken once the bug is fixed.
+void * __attribute__((noinline))
+boundscheck_debug (DebugPoolTy * Pool, void * Source, void * Dest, TAG, const char * SourceFile, unsigned lineno) {
+  // This code is inlined at all boundscheck() calls
+
+  // Search the splay for Source and return the bounds of the object
+  void * ObjStart = Source, * ObjEnd = 0;
+  bool ret = boundscheck_lookup (Pool, ObjStart, ObjEnd); 
+
+  if (logregs) {
+    fprintf (stderr, "boundscheck_debug(%d): %d: %p - %p\n", tag, ret, ObjStart, ObjEnd);
+    fflush (stderr);
+  }
+
+  // Check if destination lies in the same object
+  if (__builtin_expect ((ret && (ObjStart <= Dest) &&
+                        ((Dest <= ObjEnd))), 1)) {
+    return Dest;
+  } else {
+    //
+    // Either:
+    //  1) A valid object was not found in splay tree, or
+    //  2) Dest is not within the valid object in which Source was found
+    //
+    return boundscheck_check (ret, ObjStart, ObjEnd, Pool, Source, Dest, true, SourceFile, lineno);  
+  }
+}
+
+//
+// Function: boundscheckui_debug()
+//
+// Description:
+//  Identical to boundscheckui() but with debug information.
+//
+// Inputs:
+//  Pool       - The pool to which the pointers (Source and Dest) should
+//               belong.
+//  Source     - The Source pointer of the indexing operation (the GEP).
+//  Dest       - The result of the indexing operation (the GEP).
+//  SourceFile - The source file in which the check was inserted.
+//  lineno     - The line number of the instruction for which the check was
+//               inserted.
+//
+void *
+boundscheckui_debug (DebugPoolTy * Pool,
+                     void * Source,
+                     void * Dest, TAG,
+                     const char * SourceFile,
+                     unsigned int lineno) {
+  // This code is inlined at all boundscheckui calls
+
+  // Search the splay for Source and return the bounds of the object
+  void * ObjStart = Source, * ObjEnd = 0;
+  bool ret = boundscheck_lookup (Pool, ObjStart, ObjEnd); 
+
+  if (logregs) {
+    fprintf (stderr, "boundscheckui_debug: %p: %p - %p\n", (void *) Pool, ObjStart, ObjEnd);
+    fflush (stderr);
+  }
+
+  // Check if destination lies in the same object
+  if (__builtin_expect ((ret && (ObjStart <= Dest) &&
+                        ((Dest <= ObjEnd))), 1)) {
+    return Dest;
+  } else {
+    //
+    // Either:
+    //  1) A valid object was not found in splay tree, or
+    //  2) Dest is not within the valid object in which Source was found
+    //
+    return boundscheck_check (ret,
+                              ObjStart,
+                              ObjEnd,
+                              Pool,
+                              Source,
+                              Dest,
+                              false,
+                              SourceFile,
+                              lineno);
+  }
+}
+
+
+//
+// Function: funccheck()
+//
+// Description:
+//  Determine whether the specified function pointer is one of the functions
+//  in the given list.
+//
+// Inputs:
+//  num - The number of function targets in the DSNode.
+//  f   - The function pointer that we are testing.
+//  g   - The first function given in the DSNode.
+//
+void
+__sc_dbg_funccheck (unsigned num, void *f, void *g, ...) {
+  va_list ap;
+  unsigned i = 0;
+
+  // Test against the first function in the list
+  if (f == g) return;
+  i++;
+  va_start(ap, g);
+  for ( ; i != num; ++i) {
+    void *h = va_arg(ap, void *);
+    if (f == h) {
+      return;
+    }
+  }
+  if (logregs) {
+  fprintf(stderr, "funccheck failed(num=%d): %p %p\n", num, f, g);
+  fflush(stderr);
+  }
+  abort();
+}
+
+
+/// Stubs
+
+void
+poolcheck (DebugPoolTy *Pool, void *Node) {
+  poolcheck_debug(Pool, Node, 0, NULL, 0);
+}
+
+void
+poolcheckui (DebugPoolTy *Pool, void *Node) {
+  //
+  // In production mode, do not report an error if an incomplete load/store
+  // check fails.  The fact that it is incomplete means that we can't tell for
+  // certain whether the pointer is invalid or if it points to a memory object
+  // that belongs to a diffeent pool or comes from external code.
+  //
+  return;
+}
+
+//
+// Function: boundscheck()
+//
+// Description:
+//  Perform a precise bounds check.  Ensure that Source is within a valid
+//  object within the pool and that Dest is within the bounds of the same
+//  object.
+//
+void *
+boundscheck (DebugPoolTy * Pool, void * Source, void * Dest) {
+  return boundscheck_debug(Pool, Source, Dest, 0, NULL, 0);
+}
+
+//
+// Function: boundscheckui()
+//
+// Description:
+//  Perform a bounds check (with lookup) on the given pointers.
+//
+// Inputs:
+//  Pool - The pool to which the pointers (Source and Dest) should belong.
+//  Source - The Source pointer of the indexing operation (the GEP).
+//  Dest   - The result of the indexing operation (the GEP).
+//
+void *
+boundscheckui (DebugPoolTy * Pool, void * Source, void * Dest) {
+  return boundscheckui_debug (Pool, Source, Dest, 0, NULL, 0);
+}
+
+//
+// Function: poolcheckalign()
+//
+// Description:
+//  Ensure that the given pointer is both within an object in the pool *and*
+//  points to the correct offset within the pool.
+//
+// Inputs:
+//  Pool   - The pool in which the pointer should be found.
+//  Node   - The pointer to check.
+//  Offset - The offset, in bytes, that the pointer should be to the beginning
+//           of objects found in the pool.
+//
+void
+poolcheckalign (DebugPoolTy *Pool, void *Node, unsigned Offset) {
+  poolcheckalign_debug(Pool, Node, Offset, 0, NULL, 0);
+}
Index: runtime/libsc/DebugRuntime/ConfigData.h
===================================================================
--- runtime/libsc/DebugRuntime/ConfigData.h	(revision 0)
+++ runtime/libsc/DebugRuntime/ConfigData.h	(revision 0)
@@ -0,0 +1,40 @@
+//===- ConfigData.h - Structures for Configuring the Run-time ---*- C++ -*-===//
+// 
+//                          The SAFECode Compiler 
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines the structure used to configure the SAFECode run-time.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CONFIGDATA_H
+#define CONFIGDATA_H
+
+namespace llvm {
+
+//
+// Structure: ConfigData
+//
+// Description:
+//  This structure tells us what the configuration of the runtime is
+//
+struct ConfigData {
+  // Flags whether objects should be remapped
+  unsigned RemapObjects;
+
+  // Flags whether strict indexing rules should be enforced
+  unsigned StrictIndexing;
+
+  // Flags whether we should track external memory allocations
+  unsigned TrackExternalMallocs;
+};
+
+extern struct ConfigData ConfigData;
+
+}
+#endif
+
Index: runtime/libsc/DebugRuntime/PageManager.cpp
===================================================================
--- runtime/libsc/DebugRuntime/PageManager.cpp	(revision 0)
+++ runtime/libsc/DebugRuntime/PageManager.cpp	(revision 0)
@@ -0,0 +1,378 @@
+//===- PageManager.cpp - Implementation of the page allocator -------------===//
+// 
+//                          The SAFECode Compiler
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PageManager.h interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ConfigData.h"
+#include "PageManager.h"
+#ifndef _POSIX_MAPPED_FILES
+#define _POSIX_MAPPED_FILES
+#endif
+
+#include "../include/MallocAllocator.h"
+#include "../include/MMAPSupport.h"
+#include "../include/HashExtras.h"
+#include "../include/BitmapAllocator.h"
+
+#include <unistd.h>
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+#include <iostream>
+#include <vector>
+#include <utility>
+
+#include "llvm/ADT/DenseMap.h"
+
+// this is for dangling pointer detection in Mac OS X
+#if defined(__APPLE__)
+#include <mach/mach_vm.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#endif
+
+namespace llvm {
+
+//
+// Structure: ShadowInfo
+//
+// Description:
+//  This structure provides information on a pre-created shadow page.
+//
+struct ShadowInfo {
+  // Start address of the shadow page
+  void * ShadowStart;
+
+  // Flag bits indicating which physical pages within the shadow are in use
+  unsigned short InUse;
+};
+
+// Map canonical pages to their shadow pages
+hash_map<void *,std::vector<struct ShadowInfo> > ShadowPages;
+
+// If not compiling on Mac OS X, define types and values to make the same code
+// work on multiple platforms.
+#if !defined(__APPLE__)
+typedef int kern_return_t;
+static const int KERN_SUCCESS=0;
+#endif
+
+#if defined(__APPLE__)
+//
+// Function: RemapPages()
+//
+// Description:
+//  This function takes a virtual, page aligned address and a length and remaps
+//  the memory so that the underlying physical pages appear in multiple
+//  locations within the virtual memory.
+//
+// Inputs:
+//  va     - Virtual address of the first page to double map.
+//  length - The length, in bytes of the memory to be remapped.
+//
+static void *
+RemapPages (void * va, unsigned length) {
+  kern_return_t      kr;
+  mach_vm_address_t  target_addr = 0;
+  mach_vm_address_t  source_addr;
+  vm_prot_t          prot_cur = VM_PROT_READ | VM_PROT_WRITE;
+  vm_prot_t          prot_max = VM_PROT_READ | VM_PROT_WRITE;
+  vm_map_t           self     = mach_task_self();
+
+  source_addr = (mach_vm_address_t) ((uintptr_t)va & ~(PPageSize - 1));
+  uintptr_t offset = (uintptr_t)va & (PPageSize - 1);
+  unsigned NumPPage = 0;
+
+  NumPPage = (length / PPageSize) + 1;
+
+  //if((unsigned)va > 0x2f000000) {
+  //  logregs = 1;
+  //}
+
+  if (logregs) {
+    fprintf (stderr, " RemapPage:117: source_addr = %p, offset = %p, NumPPage = %d\n", (void*)source_addr, (void *) offset, NumPPage);
+    fflush(stderr);
+  }
+
+#if 0
+  // FIX ME!! when there's time, check out why this doesn't work
+  if ( (length - (NumPPage-1) * PPageSize) > (PPageSize - offset) ) {
+    NumPPage++;
+    length = NumPPage * PPageSize;
+  }
+#endif
+
+  uintptr_t byteToMap = length + offset;
+
+  if (logregs) {
+    fprintf(stderr, " RemapPage127: remapping page of size %p covering %d page with offset %p and byteToMap = %p",
+    (void *) length, NumPPage, (void *) offset, (void *) byteToMap);
+    fflush(stderr);
+  }
+  kr = mach_vm_remap (self,
+                      &target_addr,
+                      byteToMap,
+                      0,
+                      TRUE,
+                      self,
+                      source_addr,
+                      FALSE,
+                      &prot_cur,
+                      &prot_max,
+                      VM_INHERIT_SHARE); 
+ 
+  if (kr != KERN_SUCCESS) {
+    fprintf(stderr, " mach_vm_remap error: %d \n", kr);
+    fprintf(stderr, " failed to remap %p of memory from source_addr = %p\n", (void *) byteToMap, (void *)source_addr);
+    //printf(" no of pages used %d %d  %d\n", AddressSpaceUsage1, AddressSpaceUsage2, AddressSpaceUsage2+AddressSpaceUsage1);
+    fprintf(stderr, "%s\n", mach_error_string(kr));
+    // Mach don't modify and don't mark the string as constants..
+    // So I use a cast to get rid of compiler warnings.
+    mach_error(const_cast<char*>("mach_vm_remap:"), kr); // just to make sure I've got this error right
+    fflush(stderr);
+    //goto repeat;
+    //abort();
+  }
+
+  if (logregs) {
+    fprintf(stderr, " RemapPage:160: remap succeeded to addr 0x%08x\n", (unsigned)target_addr);
+    fflush(stderr);
+  }
+  va = (void *) target_addr;
+  return va;
+ 
+/* 
+#ifdef STATISTIC
+   AddressSpaceUsage2++;
+#endif
+*/
+}
+#else
+void *
+RemapPages (void * va, unsigned length) {
+  void *  target_addr = 0;
+  void *  source_addr;
+  void *  finish_addr;
+
+  //
+  // Find the beginning and end of the physical pages for this memory object.
+  //
+  source_addr = (void *) ((unsigned long)va & ~(PPageSize - 1));
+  finish_addr = (void *) (((unsigned long)va + length) & ~(PPageSize - 1));
+
+  unsigned int NumPages = ((uintptr_t)finish_addr - (uintptr_t)source_addr) / PPageSize;
+  if (!NumPages) NumPages = 1;
+
+  //
+  // Find the length in bytes of the memory we want to remap.
+  //
+  ptrdiff_t map_length = ((intptr_t) finish_addr - (intptr_t) source_addr) + PPageSize - 1;
+
+  //
+  // The below code seems to double map physical memory correctly.  However,
+  // it does not remap the memory pages that the caller has requested.  I
+  // suspect the code to calculate the length and address is somehow incorrect
+  // and needs to be fixed.
+  //
+  // target_addr = mremap (va, 0, PPageSize, MREMAP_MAYMOVE);
+
+#if 0
+fprintf (stderr, "remap: %p %x -> %p %x\n", va, map_length, source_addr, map_length);
+fflush (stderr);
+#endif
+  target_addr = mremap (source_addr, 0, map_length, MREMAP_MAYMOVE);
+  if (target_addr == MAP_FAILED) {
+    perror ("RemapPage: Failed to create shadow page: ");
+  }
+
+#if 0
+  volatile unsigned int * p = (unsigned int *) source_addr;
+  volatile unsigned int * q = (unsigned int *) target_addr;
+
+  p[0] = 0xbeefbeef;
+fprintf (stderr, "value: %p=%x, %p=%x\n", (void *) p, p[0], (void *) q, q[0]);
+  p[0] = 0xdeeddeed;
+fprintf (stderr, "value: %p=%x, %p=%x\n", (void *) p, p[0], (void *) q, q[0]);
+fflush (stderr);
+#endif
+  return target_addr;
+}
+#endif
+
+//
+// Function: RemapObject()
+//
+// Description:
+//  Create another mapping of the memory object so that it appears in multiple
+//  locations of the virtual address space.
+//
+// Inputs:
+//  va     - Virtual address of the memory object to remap.  It does not need
+//           to be page aligned.
+//
+//  length - The length of the memory object in bytes.
+//
+// Return value:
+//  Returns a pointer *to the page* that was remapped.
+//
+// Notes:
+//  This function must generally determine the set of pages occupied by the
+//  memory object and remap those pages.  This is because most operating
+//  systems can only remap memory at page granularity.
+//
+// TODO:
+//  The constant 12 used to compute StartPage only works when the physical page
+//  size is 4096.  We need to make that configurable.
+//
+void *
+RemapObject (void * va, unsigned length) {
+  // Start of the page in which the object lives
+  unsigned char * page_start;
+
+  // Start of the physical page in which the object lives
+  unsigned char * phy_page_start;
+
+  // The offset within the physical page in which the object lives
+  uintptr_t phy_offset = (unsigned long)va & (PPageSize - 1);
+  //  unsigned offset     = (unsigned long)va & (PageSize - 1);
+
+  //
+  // Compute the location of the object relative to the page and physical page.
+  //
+  page_start     = (unsigned char *)((uintptr_t)va & ~(PageSize - 1));
+  phy_page_start = (unsigned char *)((uintptr_t)va & ~(PPageSize - 1));
+
+  uintptr_t StartPage = ((uintptr_t)phy_page_start >> 12) -
+                        ((uintptr_t)page_start     >> 12);
+  //unsigned EndPage   = ((phy_page_start + length - page_start) / PPageSize) + 1;
+
+  //
+  // If we're not remapping objects, don't do anything.
+  //
+  if (ConfigData.RemapObjects == false)
+    return (void *)(phy_page_start);
+
+  // Create a mask to easily tell if the needed pages are available
+  uintptr_t mask = 0;
+  for (uintptr_t i = StartPage; i < PageMultiplier; ++i) {
+    if (((unsigned char *)(page_start) + i*PPageSize) <= ((unsigned char *)(va)+length) )
+      mask |= (1u << i);
+    else
+      break;
+  }
+
+  //
+  // First, look to see if a pre-existing shadow page is available.
+  //
+  if (ShadowPages.find(page_start) != ShadowPages.end()) {
+    uintptr_t numfull = 0;
+    for (uintptr_t i = 0; i < NumShadows; ++i) {
+      struct ShadowInfo Shadow = ShadowPages[page_start][i];
+      if ((Shadow.ShadowStart) && ((Shadow.InUse & mask) == 0)) {
+        // Set the shadow pages as being used
+        ShadowPages[page_start][i].InUse |= mask;
+
+        // Return the pre-created shadow page
+        return ((unsigned char *)(Shadow.ShadowStart) + (phy_page_start - page_start));
+      }
+
+      // Keep track of how many shadows are full
+      if (Shadow.InUse == 0xffff) ++numfull;
+    }
+
+    //
+    // If all of the shadow pages are full, remove this entry from the set of
+    // ShadowPages.
+    //
+    if (numfull == NumShadows) {
+      ShadowPages.erase(page_start);
+    }
+  }
+
+  //
+  // We could not find a pre-existing shadow page.  Create a new one.
+  //
+  void * p = (RemapPages (phy_page_start, length + phy_offset));
+  assert (p && "New remap failed!\n");
+  return p;
+}
+
+/// AllocatePage - This function returns a chunk of memory with size and
+/// alignment specified by PageSize.
+void *AllocatePage() {
+  FreePagesListType &FPL = FreePages;
+
+  if (!FPL.empty()) {
+    void *Result = FPL.back();
+      FPL.pop_back();
+      return Result;
+  }
+
+  // Allocate several pages, and put the extras on the freelist...
+  char *Ptr = (char*)GetPages(NumToAllocate);
+
+  // Place all but the first page into the page cache
+  for (unsigned i = 1; i != NumToAllocate; ++i) {
+    FPL.push_back (Ptr+i*PageSize);
+  }
+
+  // Create several shadow mappings of all the pages
+  if (ConfigData.RemapObjects) {
+    char * NewShadows[NumShadows];
+    for (unsigned i=0; i < NumShadows; ++i) {
+      NewShadows[i] = (char *) RemapPages (Ptr, NumToAllocate * PageSize);
+    }
+
+    // Place the shadow pages into the shadow cache
+    for (unsigned i = 0; i != NumToAllocate; ++i) {
+      char * PagePtr = Ptr+i*PageSize;
+      std::vector<struct ShadowInfo> & Shadows = ShadowPages[(void*)PagePtr];
+      Shadows.reserve(NumShadows);
+      for (unsigned j=0; j < NumShadows; ++j) {
+        Shadows[j].ShadowStart = NewShadows[j]+(i*PageSize);
+        Shadows[j].InUse       = 0;
+      }
+    }
+  }
+
+  return Ptr;
+}
+
+
+// ProtectShadowPage - Protects shadow page that begins at beginAddr, spanning
+//                     over PageNum
+void
+ProtectShadowPage (void * beginPage, unsigned NumPPages)
+{
+  kern_return_t kr;
+  if (ConfigData.RemapObjects) {
+    kr = mprotect(beginPage, NumPPages * PPageSize, PROT_NONE);
+    if (kr != KERN_SUCCESS)
+      perror(" mprotect error: Failed to protect shadow page\n");
+  }
+  return;
+}
+
+// UnprotectShadowPage - Unprotects the shadow page in the event of fault when
+//                       accessing protected shadow page in order to
+//                       resume execution
+void
+UnprotectShadowPage (void * beginPage, unsigned NumPPages)
+{
+  kern_return_t kr;
+  kr = mprotect(beginPage, NumPPages * PPageSize, PROT_READ | PROT_WRITE);
+  if (kr != KERN_SUCCESS)
+    perror(" unprotect error: Failed to make shadow page accessible \n");
+  return;
+}
+
+}
Index: runtime/libsc/DebugRuntime/RewritePtr.cpp
===================================================================
--- runtime/libsc/DebugRuntime/RewritePtr.cpp	(revision 0)
+++ runtime/libsc/DebugRuntime/RewritePtr.cpp	(revision 0)
@@ -0,0 +1,181 @@
+//===- RewritePtr.cpp --------------------------------------------------- -===//
+// 
+//                          The SAFECode Compiler
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements functions to rewrite out of bounds pointers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PageManager.h"
+#include "PoolAllocator.h"
+#include "DebugReport.h"
+#include "RewritePtr.h"
+
+#include "llvm/ADT/DenseMap.h"
+
+#include "../include/DebugRuntime.h"
+
+#include <cstdio>
+#include <map>
+
+extern FILE * ReportLog;
+using namespace llvm; 
+
+namespace llvm {
+
+DebugPoolTy OOBPool;
+
+// Map between rewrite pointer and source file information
+llvm::DenseMap<void *, const char*>  RewriteSourcefile;
+llvm::DenseMap<void *, unsigned>     RewriteLineno;
+std::map<const void *, const void *> RewrittenPointers;
+
+// Record from which object an OOB pointer originates
+llvm::DenseMap<void *, std::pair<const void *, const void * > > RewrittenObjs;
+
+//
+// Function: rewrite_ptr()
+//
+// Description:
+//  Take the given pointer and rewrite it to an Out Of Bounds (OOB) pointer.
+//
+// Inputs:
+//  Pool       - The pool in which the pointer should be located (but isn't).
+//               This value can be NULL if the caller doesn't know the pool.
+//  p          - The pointer that needs to be rewritten.
+//  ObjStart   - The address of the first valid byte of the object.
+//  ObjEnd     - The address of the last valid byte of the object.
+//  SourceFile - The name of the source file in which the check requesting the
+//               rewrite is located.
+//  lineno     - The line number within the source file in which the check
+//               requesting the rewrite is located.
+//
+void *
+rewrite_ptr (DebugPoolTy * Pool,
+             const void * p,
+             const void * ObjStart,
+             const void * ObjEnd,
+             const char * SourceFile,
+             unsigned lineno) {
+
+  static unsigned char * invalidptr = 0;
+
+  //
+  // If this pointer has already been rewritten, do not rewrite it again.
+  //
+  if (RewrittenPointers.find (p) != RewrittenPointers.end()) {
+    return const_cast<void*>(RewrittenPointers[p]);
+  }
+
+  //
+  // Calculate a new rewrite pointer.
+  //
+  if (invalidptr == 0) invalidptr = (unsigned char*)InvalidLower;
+  ++invalidptr;
+
+  //
+  // Ensure that we haven't run out of rewrite pointers.
+  //
+  void* P = invalidptr;
+  if ((uintptr_t) P == InvalidUpper) {
+    fprintf (stderr, "rewrite: out of rewrite ptrs: %p %p, pc=%p\n",
+             (void *) InvalidLower, (void *) InvalidUpper, invalidptr);
+    fflush (stderr);
+    return const_cast<void*>(p);
+  }
+
+  //
+  // If no pool was specified (as is the case for an ExactCheck), use a
+  // special Out of Bounds Pointer pool.
+  //
+  if (!Pool) Pool = &OOBPool;
+
+  //
+  // Determine if this pointer value has already been rewritten.  If so, just
+  // return the previously rewritten value.  Otherwise, insert a mapping from
+  // rewrite pointer to original pointer into the pool.
+  //
+  Pool->OOB.insert (invalidptr, ((unsigned char *)(invalidptr)), const_cast<void*>(p));
+
+  //
+  // If debugging tool support is enabled, then insert it into the global
+  // OOB pool as well; this will ensure that we can find the pointer on a
+  // memory protection violation (on faults, we don't have Pool handle
+  // information).
+  //
+  if (logregs) {
+    fprintf (ReportLog, "rewrite: %p: %p -> %p\n", (void*) Pool, p, invalidptr);
+    fflush (ReportLog);
+  }
+
+  OOBPool.OOB.insert (invalidptr, ((unsigned char *)(invalidptr)), const_cast<void*>(p));
+  RewriteSourcefile[invalidptr] = SourceFile;
+  RewriteLineno[invalidptr] = lineno;
+  RewrittenPointers[p] = invalidptr;
+  RewrittenObjs[invalidptr] = std::make_pair(ObjStart, ObjEnd);
+  return invalidptr;
+}
+
+}
+
+//
+// Function: getActualValue()
+//
+// Description:
+//  If src is an out of object pointer, get the original value.
+//
+void *
+pchk_getActualValue (DebugPoolTy * Pool, void * p) {
+  //
+  // If the pointer is not within the rewrite pointer range, then it is not a
+  // rewritten pointer.  Simply return its current value.
+  //
+  if (((uintptr_t)p <= InvalidLower) || ((uintptr_t)p >= InvalidUpper)) {
+    return p;
+  }
+
+  void * src = 0;
+  void* tag = 0;
+  void * end = 0;
+
+  //
+  // Look for the pointer in the pool's OOB pointer list.  If we find it,
+  // return its actual value.
+  //
+  if (Pool && (Pool->OOB.find(p, src, end, tag))) {
+    if (logregs) {
+      fprintf (ReportLog, "getActualValue(1): %p: %p -> %p\n", (void*)Pool, p, tag);
+      fflush (ReportLog);
+    }
+    return tag;
+  }
+
+  //
+  // If we can't find the pointer in the pool's OOB list, perhaps it's in the
+  // global OOB Pool (this can happen when it's rewritten by an exact check).
+  //
+  if (OOBPool.OOB.find (p, src, end, tag)) {
+    if (logregs) {
+      fprintf (ReportLog, "getActualValue(2): %p: %p -> %p\n", (void*)&OOBPool, p, tag);
+      fflush (ReportLog);
+    }
+    return tag;
+  }
+
+  //
+  // If we can't find the pointer, no worries.  If the program tries to use the
+  // pointer, another SAFECode checks should flag a failure.  In this case,
+  // just return the pointer.
+  //
+  if (logregs) {
+    fprintf (ReportLog, "getActualValue(3): %p: %p -> %p\n", (void*)Pool, p, p);
+    fflush (ReportLog);
+  }
+  return p;
+}
+
Index: runtime/libsc/DebugRuntime/Report.cpp
===================================================================
--- runtime/libsc/DebugRuntime/Report.cpp	(revision 0)
+++ runtime/libsc/DebugRuntime/Report.cpp	(revision 0)
@@ -0,0 +1,109 @@
+//===- Report.cpp -------------------------------------------*- C++ -*-----===//
+// 
+//                       The SAFECode Compiler Project
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements functions for creating reports for the SAFECode
+// run-time.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../include/Report.h"
+
+#include <iostream>
+#include <cstdlib>
+
+namespace llvm {
+
+ViolationInfo::~ViolationInfo() {}
+
+void
+ViolationInfo::print(std::ostream & OS) const {
+  //
+  // Print a single line report describing the error.  This is used, I believe,
+  // by the automatic testing infrastructure scripts to determine if a safety
+  // violation was correctly detected.
+  //
+  OS << std::showbase << std::hex 
+     << "SAFECode:Violation Type " << this->type << " "
+     << "when accessing  " << this->faultPtr << " "
+     << "at IP=" << this->faultPC << std::endl;
+
+  //
+  // Determine which descriptive string to use to describe the error.
+  //
+  const char * typestring;
+  switch (type) {
+    case FAULT_DANGLING_PTR:
+      typestring = "Use After Free Error";
+      break;
+
+    case FAULT_INVALID_FREE:
+      typestring = "Invalid Free Error";
+      break;
+
+    case FAULT_NOTHEAP_FREE:
+      typestring = "Freeing Non-Heap Object Error";
+      break;
+
+    case FAULT_DOUBLE_FREE:
+      typestring = "Double Free Error";
+      break;
+
+    case FAULT_OUT_OF_BOUNDS:
+      typestring = "Out of Bounds Error";
+      break;
+
+    case FAULT_WRITE_OUT_OF_BOUNDS:
+      typestring = "Writing Out of Bounds Error";
+      break;
+
+    case FAULT_LOAD_STORE:
+      typestring = "Load/Store Error";
+      break;
+
+    case WARN_LOAD_STORE:
+      typestring = "Potential Load/Store Error";
+      break;
+
+    case FAULT_ALIGN:
+      typestring = "Alignment Error";
+      break;
+
+    case FAULT_UNINIT:
+      typestring = "Uninitialized/NULL Pointer Error";
+      break;
+
+    case FAULT_CSTDLIB:
+      typestring = "C Library Undefined Behavior";
+      break;
+
+    default:
+      typestring = "Unknown Error";
+      break;
+  }
+
+  //
+  // Now print a more human readable version of the error.
+  //
+  OS << "\n";
+  OS << "=======+++++++    SAFECODE RUNTIME ALERT +++++++=======\n";
+  OS << "= Error type                            :\t" << typestring << "\n";
+  OS << "= Faulting pointer                      :\t" << this->faultPtr << "\n";
+  OS << "= Program counter                       :\t" << this->faultPC << "\n";
+}
+
+void
+ReportMemoryViolation(const ViolationInfo *v) {
+	v->print(std::cerr);
+  static unsigned count = 20;
+  --count;
+  if (!count) abort();
+  return;
+}
+
+}
Index: runtime/libsc/DebugRuntime/MallocHooks.cpp
===================================================================
--- runtime/libsc/DebugRuntime/MallocHooks.cpp	(revision 0)
+++ runtime/libsc/DebugRuntime/MallocHooks.cpp	(revision 0)
@@ -0,0 +1,156 @@
+//===- MallocHooks.cpp - Implementation of hooks to malloc() functions ----===//
+// 
+//                            The SAFECode Compiler
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements functions that interrupt and record allocations created
+// by the system's original memory allocators.  This allows the SAFECode
+// compiler to work with external code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../include/SplayTree.h"
+
+#if defined(__APPLE__)
+#include <malloc/malloc.h>
+#endif
+
+namespace llvm {
+
+// Splay tree for recording external allocations
+RangeSplaySet<> * ExternalObjects;
+
+#if defined(__APPLE__)
+// The real allocation functions
+static void * (*real_malloc)  (malloc_zone_t *, size_t);
+static void * (*real_calloc)  (malloc_zone_t *, size_t, size_t);
+static void * (*real_valloc)  (malloc_zone_t *, size_t);
+static void * (*real_realloc) (malloc_zone_t *, void *, size_t);
+static void   (*real_free)    (malloc_zone_t *, void *);
+
+// Prototypes for the tracking versions
+static void * track_malloc  (malloc_zone_t *, size_t size);
+static void * track_calloc  (malloc_zone_t *, size_t num_items, size_t size);
+static void * track_valloc  (malloc_zone_t *, size_t size);
+static void * track_realloc (malloc_zone_t *, void * p, size_t size);
+static void   track_free    (malloc_zone_t *, void * p);
+
+void
+installAllocHooks (void) {
+  // Pointer to the default malloc zone
+  malloc_zone_t * default_zone;
+
+  //
+  // Get the default malloc zone and record the pointers to the real malloc
+  // functions.
+  //
+  default_zone = malloc_default_zone();
+  real_malloc  = default_zone->malloc;
+  real_calloc  = default_zone->calloc;
+  real_valloc  = default_zone->valloc;
+  real_realloc = default_zone->realloc;
+  real_free    = default_zone->free;
+
+  //
+  // Install intercept routines.
+  //
+  default_zone->malloc = track_malloc;
+  default_zone->calloc  = track_calloc;
+  default_zone->valloc  = track_valloc;
+  default_zone->realloc = track_realloc;
+  default_zone->free    = track_free;
+}
+
+static void *
+track_malloc (malloc_zone_t * zone, size_t size) {
+  // Pointer to the allocated object
+  char * objp;
+
+  //
+  // Perform the allocation.
+  //
+  objp = (char*) real_malloc (zone, size);
+
+  //
+  // Record the allocation and return to the caller.
+  //
+  ExternalObjects->insert(objp, objp + size);
+  return objp;
+}
+
+static void *
+track_valloc (malloc_zone_t * zone, size_t size) {
+  // Pointer to the allocated object
+  char * objp;
+
+  //
+  // Perform the allocation.
+  //
+  objp = (char*) real_valloc (zone, size);
+
+  //
+  // Record the allocation and return to the caller.
+  //
+  ExternalObjects->insert(objp, objp + size);
+  return objp;
+}
+
+static void *
+track_calloc (malloc_zone_t * zone, size_t num, size_t size) {
+  // Pointer to the allocated object
+  char * objp;
+
+  //
+  // Perform the allocation.
+  //
+  objp = (char*) real_calloc (zone, num, size);
+
+  //
+  // Record the allocation and return to the caller.
+  //
+  ExternalObjects->insert(objp, objp + num * size);
+  return objp;
+}
+
+static void *
+track_realloc (malloc_zone_t * zone, void * oldp, size_t size) {
+  // Pointer to the allocated object
+  char * objp;
+
+  //
+  // Perform the allocation.
+  //
+  objp = (char*) real_realloc (zone, oldp, size);
+
+  //
+  // Record the allocation and return to the caller.
+  //
+  ExternalObjects->insert(objp, objp + size);
+  return objp;
+}
+
+static void
+track_free (malloc_zone_t * zone, void * p) {
+  //
+  // Perform the allocation.
+  //
+  real_free (zone, p);
+
+  //
+  // Record the allocation and return to the caller.
+  //
+  ExternalObjects->remove(p);
+  return;
+}
+#else
+void
+installAllocHooks (void) {
+  return;
+}
+#endif
+
+}
Index: runtime/libsc/DebugRuntime/RewritePtr.h
===================================================================
--- runtime/libsc/DebugRuntime/RewritePtr.h	(revision 0)
+++ runtime/libsc/DebugRuntime/RewritePtr.h	(revision 0)
@@ -0,0 +1,108 @@
+//===- RewritePtr.h - Header file for Rewrite Pointers ----------*- C++ -*-===//
+// 
+//                         The SAFECode Compiler
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines functions for use with rewrite pointers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _SC_REWRITEPTR_H
+#define _SC_REWRITEPTR_H
+
+namespace llvm {
+
+//
+// The lower and upper bound of an unmapped memory region.  This range is used
+// for rewriting pointers that go one beyond the edge of an object so that they
+// can be used for comparisons but will generate a fault if used for loads or
+// stores.
+//
+// There are a few restrictions:
+//  1) I *think* InvalidUpper must be on a page boundary.
+//  2) None of the values can be reserved pointer values.  Such values include:
+//      0 - This is the NULL pointer.
+//      1 - This is a reserved pointer in the Linux kernel.
+//      2 - This is another reserved pointer in the Linux kernel.
+//
+// Here's the breakdown of how it works on various operating systems:
+//  o) Linux           - We use the kernel's reserved address space (which is
+//                       inaccessible from applications).
+//  o) Other platforms - We allocate a range of memory and disable read and
+//                       write permissions for the pages contained within it.
+//
+#if defined(__linux__)
+static const uintptr_t InvalidUpper = 0xf0000000;
+static const uintptr_t InvalidLower = 0xc0000000;
+#else
+extern uintptr_t InvalidUpper;
+extern uintptr_t InvalidLower;
+#endif
+
+// Map between rewrite pointer and source file information
+extern llvm::DenseMap<void *, const char*>  RewriteSourcefile;
+extern llvm::DenseMap<void *, unsigned>     RewriteLineno;
+extern std::map<const void *, const void *> RewrittenPointers;
+
+//
+// Function: isRewritePtr()
+//
+// Description:
+//  Determines whether the specified pointer value is a rewritten value for an
+//  Out-of-Bounds pointer value.
+//
+// Return value:
+//  true  - The pointer value is an OOB pointer rewrite value.
+//  false - The pointer value is the actual value of the pointer.
+//
+static inline bool
+isRewritePtr (void * p) {
+  uintptr_t ptr = (uintptr_t) p;
+
+  if ((InvalidLower < ptr ) && (ptr < InvalidUpper))
+    return true;
+  return false;
+}
+
+//
+// Function: getOOBObject()
+//
+// Description:
+//  Given a pointer, determine if it is an OOB pointer.  If it is, determine
+//  the bounds of the object from whence it came and return them to the caller.
+//
+// Inputs:
+//  p - The pointer for which bounds information is requested.
+//
+// Outputs:
+//  start - The first address of the memory object.
+//  end   - The last valid address of the memory object.
+//
+// Return value:
+//  true  - The pointer was an OOB pointer.
+//  false - The pointer was not an OOB pointer.
+//
+static inline bool
+getOOBObject (void * p, void * & start, void * & end) {
+  // Record from which object an OOB pointer originates
+  extern llvm::DenseMap<void *, std::pair<const void *, const void * > >
+  RewrittenObjs;
+
+  if (isRewritePtr (p)) {
+    // FIXME: the casts are hacks to deal with the C++ type system
+    start = const_cast<void*>(RewrittenObjs[p].first);
+    end   = const_cast<void*>(RewrittenObjs[p].second);
+    return true;
+  }
+
+  return false;
+}
+
+}
+
+#endif
+
Index: runtime/libsc/DebugRuntime/PageManager.h
===================================================================
--- runtime/libsc/DebugRuntime/PageManager.h	(revision 0)
+++ runtime/libsc/DebugRuntime/PageManager.h	(revision 0)
@@ -0,0 +1,42 @@
+//===- PageManager.h - Allocates memory on page boundaries ------*- C++ -*-===//
+// 
+//                          The SAFECode Compiler 
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface used by the pool allocator to allocate memory
+// on large alignment boundaries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _SC_DEBUG_PAGEMANAGER_H_
+#define _SC_DEBUG_PAGEMANAGER_H_
+
+#include "../include/PageManager.h"
+
+namespace llvm {
+
+/// Special implemetation for dangling pointer detection
+
+// RemapObject - This function is used by the dangling pool allocator in order
+//               to remap canonical pages to shadow pages.
+void * RemapObject(void* va, unsigned NumByte);
+
+// MProtectPage - Protects Page passed in by argument, raising an exception
+//                or traps at future access to Page
+void MProtectPage(void * Page, unsigned NumPages);
+
+// ProtectShadowPage - Protects shadow page that begins at beginAddr, spanning
+//                     over NumPages
+void ProtectShadowPage(void * beginPage, unsigned NumPPages);
+
+// UnprotectShadowPage - Unprotects the shadow page in the event of fault when
+//                       accessing protected shadow page in order to
+//                       resume execution
+void UnprotectShadowPage(void * beginPage, unsigned NumPPage);
+
+}
+#endif
Index: runtime/libsc/DebugRuntime/PoolAllocator.h
===================================================================
--- runtime/libsc/DebugRuntime/PoolAllocator.h	(revision 0)
+++ runtime/libsc/DebugRuntime/PoolAllocator.h	(revision 0)
@@ -0,0 +1,40 @@
+//===- PoolAllocator.h - Pool allocator runtime interface file --*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface which is implemented by the LLVM pool
+// allocator runtime library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _SC_POOLALLOCATOR_RUNTIME_H_
+#define _SC_POOLALLOCATOR_RUNTIME_H_
+
+#include "../include/DebugRuntime.h"
+
+#include "llvm/ADT/DenseMap.h"
+
+#include <map>
+
+namespace llvm {
+
+extern DebugPoolTy dummyPool;
+
+// Splay tree of external objects
+extern RangeSplaySet<> * ExternalObjects;
+
+// Records Out of Bounds pointer rewrites; also used by OOB rewrites for
+// exactcheck() calls
+extern DebugPoolTy OOBPool;
+
+// Record from which object an OOB pointer originates
+//extern llvm::DenseMap<void *, std::pair<const void *, const void * > > RewrittenObjs;
+
+
+}
+#endif
Index: runtime/libsc/DebugRuntime/DebugReport.cpp
===================================================================
--- runtime/libsc/DebugRuntime/DebugReport.cpp	(revision 0)
+++ runtime/libsc/DebugRuntime/DebugReport.cpp	(revision 0)
@@ -0,0 +1,168 @@
+//===- Report.h - Debugging reports for bugs found by SAFECode ------------===//
+// 
+//                       The SAFECode Compiler Project
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements functions for creating reports for the SAFECode
+// run-time.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugReport.h"
+
+#include <iostream>
+
+namespace llvm {
+
+void
+DebugViolationInfo::print(std::ostream & OS) const {
+  //
+  // Print out the regular error information.
+  //
+  ViolationInfo::print(OS);
+
+  //
+  // Print the source filename and line number.
+  //
+  OS << "= Fault PC Source                       :\t"
+     << (this->SourceFile ? this->SourceFile : "<unknown>")
+     << ":" << std::dec << this->lineNo << "\n";
+
+  //
+  // Print the pool handle.
+  //
+#if 1
+  OS << "= Pool Handle                           :\t" << this->PoolHandle << "\n";
+#endif
+
+  //
+  // Print the debug metata.
+  //
+  if (dbgMetaData) {
+    dbgMetaData->print(OS);
+  }
+}
+
+void
+OutOfBoundsViolation::print(std::ostream & OS) const {
+  //
+  // Print out the regular error information.
+  //
+  DebugViolationInfo::print(OS);
+
+  //
+  // Print information on the start and end locations of the object.
+  //
+  OS << "= Object start                          :\t" 
+     << std::showbase << std::hex << this->objStart << "\n"
+     << "= Object length                         :\t"
+     << this->objLen << "\n";
+}
+
+void
+AlignmentViolation::print(std::ostream & OS) const {
+  //
+  // Print out the regular error information.
+  //
+  OutOfBoundsViolation::print(OS);
+
+  //
+  // Print information on the alignment requirements for the object.
+  //
+  OS << "= Alignment                             :\t" 
+     << std::showbase << std::hex << this->alignment << "\n";
+}
+
+void
+WriteOOBViolation::print(std::ostream & OS) const {
+  //
+  // Print out the regular error information.
+  //
+  DebugViolationInfo::print(OS);
+
+  //
+  // Print information on the writing (or copying) out of bounds.
+  //
+  if (-1 != this->srcSize) {
+    OS << std::dec
+       << "= Source size (in bytes)                :\t" 
+       << this->srcSize << "\n";
+  }
+
+  OS << std::dec
+     << "= Destination size (in bytes)           :\t"
+     << this->dstSize << "\n";
+
+  if (-1 != this->copied) {
+    OS << std::dec
+       << "= Number of bytes copied                :\t"
+       << this->copied << "\n";
+  }
+}
+
+void
+CStdLibViolation::print(std::ostream & OS) const {
+  //
+  // Print out the regular error information.
+  //
+  DebugViolationInfo::print(OS);
+
+  //
+  // Print the name of the the library function in which the error occurred.
+  //
+  if (function != 0) {
+    OS << "= Library function                      :\t"
+       << function << "\n";
+  }
+
+}
+
+void
+DebugMetaData::print(std::ostream & OS) const {
+  //
+  // Only print the cononical address when debugging SAFECode itself.
+  // The MMU remapping magic should not be exposed to the programmer during
+  // regular operation.
+  //
+#if 0
+  OS << "= Canonical object address              :\t" << std::hex
+     << this->canonAddr << "\n";
+#endif
+
+  //
+  // Print object allocation information if available.
+  //
+  OS << "=\n"
+     << "= Object allocated at PC                :\t" << std::hex
+     << this->allocPC << "\n"
+     << "= Allocated in Source File              :\t"
+     << (this->SourceFile ? (char *) this->SourceFile : "<unknown>")
+     << ":" << std::dec << this->lineno << "\n";
+  if (this->allocID) {
+    OS << "= Object allocation sequence number     :\t" << std::dec
+       << this->allocID << "\n";
+  }
+
+  //
+  // Print deallocation information if it is available.
+  //
+  if (this->freeID) {
+    OS << "=\n"
+       << "= Object freed at PC                    :\t" << std::hex
+       << this->freePC << "\n";
+    OS << "= Freed in Source File                  :\t"
+       << (this->FreeSourceFile ? (char *) this->FreeSourceFile : "<unknown>")
+       << ":" << std::dec << this->Freelineno << "\n";
+    OS << "= Object free sequence number           :\t" << std::dec
+       << this->freeID << "\n";
+  }
+
+  OS << std::flush;
+  return;
+}
+
+}
Index: runtime/libsc/DebugRuntime/PoolAllocatorBitMask.cpp
===================================================================
--- runtime/libsc/DebugRuntime/PoolAllocatorBitMask.cpp	(revision 0)
+++ runtime/libsc/DebugRuntime/PoolAllocatorBitMask.cpp	(revision 0)
@@ -0,0 +1,1722 @@
+//===- PoolAllocatorBitMask.cpp - Implementation of poolallocator runtime -===//
+// 
+//                          The SAFECode Compiler
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file is one possible implementation of the LLVM pool allocator runtime
+// library.
+//
+// This uses the 'Ptr1' field to maintain a linked list of slabs that are either
+// empty or are partially allocated from.  The 'Ptr2' field of the PoolTy is
+// used to track a linked list of slabs which are full, ie, all elements have
+// been allocated from them.
+//
+//===----------------------------------------------------------------------===//
+// NOTES:
+//  1) Some of the bounds checking code may appear strange.  The reason is that
+//     it is manually inlined to squeeze out some more performance.  Please
+//     don't change it.
+//
+//  2) This run-time performs MMU re-mapping of pages to perform dangling
+//     pointer detection.  A "shadow" address is the address of a memory block
+//     that has been remapped to a new virtal address; the shadow address is
+//     returned to the caller on allocation and is unmapped on deallocation.
+//     A "canonical" address is the virtual address of memory as it is mapped
+//     in the pool slabs; the canonical address is remapped to different shadow
+//     addresses each time that particular piece of memory is allocated.
+//
+//     In normal operation, the shadow address and canonical address are
+//     identical.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ConfigData.h"
+#include "PoolAllocator.h"
+#include "PageManager.h"
+#include "DebugReport.h"
+#include "RewritePtr.h"
+
+#include "../include/DebugRuntime.h"
+
+#include <cstring>
+
+// This must be defined for Snow Leopard to get the ucontext definitions
+#if defined(__APPLE__)
+#define _XOPEN_SOURCE 1
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <signal.h>
+#include <ucontext.h>
+#include <sys/mman.h>
+#if 0
+#include <sys/ucontext.h>
+#endif
+
+#include <pthread.h>
+
+#define TAG unsigned tag
+
+#define DEBUG(x)
+
+namespace llvm {
+
+// Dummy pool for holding global memory object information
+DebugPoolTy dummyPool;
+
+// Structure defining configuration data
+struct ConfigData ConfigData = {false, true, false};
+
+// Invalid address range
+#if !defined(__linux__)
+uintptr_t InvalidUpper = 0x00000000;
+uintptr_t InvalidLower = 0x00000003;
+#endif
+
+// Splay tree for mapping shadow pointers to canonical pointers
+static RangeSplayMap<void *> ShadowMap;
+
+}
+
+using namespace llvm;
+
+// Map between call site tags and allocation sequence numbers
+std::map<unsigned,unsigned> allocSeqMap;
+std::map<unsigned,unsigned> freeSeqMap;
+
+/// UNUSED in production version
+FILE * ReportLog = 0;
+
+// Configuration for C code; flags that we should stop on the first error
+unsigned StopOnError = 0;
+
+// signal handler
+static void bus_error_handler(int, siginfo_t *, void *);
+
+// creates a new PtrMetaData structure to record pointer information
+static void * getCanonicalPtr (void * ShadowPtr);
+static inline void updatePtrMetaData(PDebugMetaData, unsigned, void *,
+                                     void *,
+                                     unsigned);
+static PDebugMetaData createPtrMetaData (unsigned,
+                                         unsigned,
+                                         allocType,
+                                         void *,
+                                         void *,
+                                         void *,
+                                         const char * SourceFile = "<unknown>",
+                                         unsigned lineno = 0);
+
+//===----------------------------------------------------------------------===//
+//
+//  Pool allocator library implementation
+//
+//===----------------------------------------------------------------------===//
+
+
+//
+// Function: pool_init_runtime()
+//
+// Description:
+//  This function is called to initialize the entire SAFECode run-time.  It
+//  configures the various run-time options for SAFECode and performs other
+//  initialization tasks.
+//
+// Inputs:
+//  Dangling   - Set to non-zero to enable dangling pointer detection.
+//  RewriteOOB - Set to non-zero to enable Out-Of-Bounds pointer rewriting.
+//  Termiante  - Set to non-zero to have SAFECode terminate when an error
+//               occurs.
+//
+
+extern "C" void __poolalloc_init();
+void
+pool_init_runtime (unsigned Dangling, unsigned RewriteOOB, unsigned Terminate) {
+  //
+  // Initialize the signal handlers for catching errors.
+  //
+  ConfigData.RemapObjects = Dangling;
+  ConfigData.StrictIndexing = !(RewriteOOB);
+  StopOnError = Terminate;
+
+  //
+  // Allocate a range of memory for rewrite pointers.
+  //
+#if !defined(__linux__)
+  const unsigned invalidsize = 1 * 1024 * 1024 * 1024;
+  void * Addr = mmap (0, invalidsize, 0, MAP_SHARED | MAP_ANON, -1, 0);
+  if (Addr == MAP_FAILED) {
+     perror ("mmap:");
+     fflush (stdout);
+     fflush (stderr);
+     assert(0 && "valloc failed\n");
+  }
+  //memset (Addr, 0x00, invalidsize);
+  madvise (Addr, invalidsize, MADV_FREE);
+  InvalidLower = (uintptr_t) Addr;
+  InvalidUpper = (uintptr_t) Addr + invalidsize;
+
+  if (logregs) {
+    fprintf (stderr, "OOB Area: %p - %p\n", (void *) InvalidLower,
+                                            (void *) InvalidUpper);
+    fflush (stderr);
+  }
+#endif
+
+  //
+  // Leave initialization of the Report logfile to the reporting routines.
+  // The libc stdio functions may have not been initialized by this point, so
+  // we cannot rely upon them working.
+  //
+  ReportLog = stderr;
+
+  //
+  // Install hooks for catching allocations outside the scope of SAFECode.
+  //
+  if (ConfigData.TrackExternalMallocs) {
+    installAllocHooks();
+  }
+
+  //
+  // Initialize the dummy pool.
+  //
+  __sc_dbg_poolinit(&dummyPool, 1, 0);
+
+  //
+  // Initialize the signal handlers for catching errors.
+  //
+  struct sigaction sa;
+  bzero (&sa, sizeof (struct sigaction));
+  sa.sa_sigaction = bus_error_handler;
+  sa.sa_flags = SA_SIGINFO;
+  if (sigaction(SIGBUS, &sa, NULL) == -1) {
+    fprintf (stderr, "sigaction installer failed!");
+    fflush (stderr);
+  }
+  if (sigaction(SIGSEGV, &sa, NULL) == -1) {
+    fprintf (stderr, "sigaction installer failed!");
+    fflush (stderr);
+  }
+
+  //
+  // This is only needed once we start using the simple pool allocator.
+  //
+#if 0
+  // Initialize all global pools
+  __poolalloc_init();
+#endif
+
+  //
+  // Initialize the splay tree of external objects.
+  //
+  ExternalObjects = new RangeSplaySet<>;
+  return;
+}
+
+//
+// Function: __sc_dbg_newpool()
+//
+// Description:
+//  Retuen a pool descriptor for a new pool.
+//
+void *
+__sc_dbg_newpool(unsigned NodeSize) {
+  DebugPoolTy * Pool = new DebugPoolTy();
+  __pa_bitmap_poolinit(static_cast<BitmapPoolTy*>(Pool), NodeSize);
+  return Pool;
+}
+
+//
+// Function: pooldestroy()
+//
+// Description:
+//  Release all memory allocated for a pool.  The compiler inserts a call to
+//  this function when it knows that all objects within the specified pool are
+//  unreachable and can be safely deallocated.
+//
+// FIXME: determine how to adjust debug logs when 
+//        pooldestroy is called
+void
+__sc_dbg_pooldestroy(DebugPoolTy * Pool) {
+  assert(Pool && "Null pool pointer passed in to pooldestroy!\n");
+
+  //
+  // Deallocate all object meta-data stored in the pool.
+  //
+  Pool->Objects.clear();
+  Pool->OOB.clear();
+  Pool->DPTree.clear();
+
+  //
+  // Let the pool allocator run-time free all objects allocated within the
+  // pool.
+  //
+  __pa_bitmap_pooldestroy(Pool);
+}
+
+//
+// Function: poolargvregister()
+//
+// Description:
+//  Register all of the argv strings in the external object pool.
+//
+void *
+poolargvregister (int argc, char ** argv) {
+  if (logregs) {
+    fprintf (stderr, "poolargvregister: %p - %p\n", (void *) argv,
+             (void *) (((unsigned char *)(&(argv[argc+1]))) - 1));
+    fflush (stderr);
+  }
+  for (int index=0; index < argc; ++index) {
+    if (logregs) {
+      fprintf (stderr, "poolargvregister: %p %u: %s\n", argv[index],
+               (unsigned)strlen(argv[index]), argv[index]);
+      fflush (stderr);
+    }
+    ExternalObjects->insert(argv[index], argv[index] + strlen (argv[index]));
+  }
+
+  //
+  // Register the actual argv array as well.  Note that the transform can
+  // do this, but it's easier to implement it here, and I doubt accessing argv
+  // strings is performance critical.
+  //
+  // Note that the argv array is supposed to end with a NULL pointer element.
+  //
+  ExternalObjects->insert(argv, ((unsigned char *)(&(argv[argc+1]))) - 1);
+
+  //
+  // Register errno for kicks and gibbles.
+  //
+  unsigned char * errnoAdd = (unsigned char *) &errno;
+  ExternalObjects->insert(errnoAdd, errnoAdd + sizeof (errno) - 1);
+
+  return argv;
+}
+
+//
+// Function: poolregister_debug()
+//
+// Description:
+//  Register the memory starting at the specified pointer of the specified size
+//  with the given Pool.  This version will also record debug information about
+//  the object being registered.
+//
+//  This function is internal to the code and handles the different types of
+//  object registrations.
+//
+static inline void
+_internal_poolregister (DebugPoolTy *Pool,
+                        void * allocaptr,
+                        unsigned NumBytes,
+                        TAG,
+                        const char * SourceFilep,
+                        unsigned lineno,
+                        allocType allocationType) {
+  // Do some initial casting for type goodness
+  const char * SourceFile = (const char *)(SourceFilep);
+
+  //
+  // Print debug information about what object the caller is trying to
+  // register.
+  //
+  if (logregs) {
+    const char * p = 0;
+    switch (allocationType) {
+      case Heap:
+        p = "Heap";
+        break;
+      case Stack:
+        p = "Stack";
+        break;
+      case Global:
+        p = "Global";
+        break;
+      default:
+        break;
+    }
+
+    fprintf (ReportLog, "poolreg_debug(%d): %p: %p-%p: %d %d %s %d: %s\n", tag,
+             (void*) Pool, (void*)allocaptr,
+             ((char*)(allocaptr)) + NumBytes - 1, NumBytes, tag, SourceFile, lineno, p);
+    fflush (ReportLog);
+  }
+
+  //
+  // If the pool is NULL or the object has zero length, don't do anything.
+  //
+  assert (NumBytes && "NumBytes must be more than zero!\n");
+  if (NumBytes == 0) return;
+
+  //
+  // If there was no pool specified, use the splay tree associated with
+  // externally allocated objects.
+  //
+  RangeSplaySet<> * SPTree = (Pool ? &(Pool->Objects) : ExternalObjects);
+
+  //
+  // Add the object to the pool's splay of valid objects.  Note that the linker
+  // may merge together global objects that are identical (or for which one is
+  // a prefix of another); allow such global objects to be reregistered.
+  //
+  if (!(SPTree->insert(allocaptr, (char*) allocaptr + NumBytes - 1))) {
+    //
+    // If it's an overlapping global object, register the larger size.
+    //
+    if (allocationType == Global) {
+      void * start;
+      void * end;
+      bool fs = SPTree->find(allocaptr, start, end);
+      assert (fs);
+      if (((unsigned char *)allocaptr + NumBytes - 1) > end) {
+        SPTree->remove (allocaptr);
+        SPTree->insert(allocaptr, (char*) allocaptr + NumBytes - 1);
+      }
+    } else {
+      assert (0 && "poolregister failed: Object already registered!\n");
+      abort();
+    }
+  }
+
+  return;
+}
+
+//
+// Function: pool_register()
+//
+// Description:
+//  Register the memory starting at the specified pointer of the specified size
+//  with the given Pool.  This version will also record debug information about
+//  the object being registered.
+//
+void
+pool_register (DebugPoolTy *Pool, void * allocaptr, unsigned NumBytes) {
+#if 0
+  //
+  // If this is a singleton object within a type-known pool, don't add it to
+  // the splay tree.
+  //
+  // FIXME: disabling because the code that does poolcheck for singleton
+  // objects, uses SearchForContainingSlab, which assumes it is being called
+  // from a poolfree, and does not handle pointers to the middle of an object.
+  if (Pool && (NumBytes == Pool->NodeSize))
+    return;
+#endif
+
+  //
+  // Heap allocations of zero size should just be ignored.
+  //
+  if (!NumBytes)
+    return;
+
+  //
+  // Use the common registration function.  Mark the allocation as a heap
+  // allocation.
+  //
+  _internal_poolregister (Pool,
+                          allocaptr,
+                          NumBytes, 0,
+                          "<unknown",
+                          0,
+                          Heap);
+  return;
+}
+
+//
+// Function: __sc_dbg_src_poolregister()
+//
+// Description:
+//  This function is externally visible and is called by code to register
+//  a heap allocation.
+//
+void
+pool_register_debug (DebugPoolTy *Pool,
+                     void * allocaptr,
+                     unsigned NumBytes, TAG,
+                     const char * SourceFilep,
+                     unsigned lineno) {
+  //
+  // Use the common registration function.  Mark the allocation as a heap
+  // allocation.  However, only do this if the object is not a singleton object
+  // within a type-known pool.
+  //
+
+  // FIXME: disabling because the code that does poolcheck for singleton
+  // objects, uses SearchForContainingSlab, which assumes it is being called
+  // from a poolfree, and does not handle pointers to the middle of an object.
+#if 0
+  if (Pool && (NumBytes == Pool->NodeSize)) {
+    return
+  }
+#endif
+
+  //
+  // Heap allocations of zero size should just be ignored.
+  //
+  if (!NumBytes)
+    return;
+
+  _internal_poolregister (Pool,
+                          allocaptr,
+                          NumBytes, tag,
+                          SourceFilep,
+                          lineno,
+                          Heap);
+
+  //
+  // Generate a generation number for this object registration.  We only do
+  // this for heap allocations.
+  //
+  unsigned allocID = (allocSeqMap[tag] += 1);
+
+  //
+  // Create the meta data object containing the debug information for this
+  // pointer.
+  //
+  PDebugMetaData debugmetadataPtr;
+  debugmetadataPtr = createPtrMetaData (allocID,
+                                        0,
+                                        Heap,
+                                        __builtin_return_address(0),
+                                        0,
+                                        getCanonicalPtr(allocaptr),
+                                        (const char *) SourceFilep, lineno);
+  dummyPool.DPTree.insert (allocaptr,
+                           (char*) allocaptr + NumBytes - 1,
+                           debugmetadataPtr);
+}
+
+//
+// Function: pool_reregister()
+//
+// Description:
+//  This is pool_register() for realloc() style allocators.  It will unregister
+//  the previously existing object (if necessary) and register the newly
+//  allocated object.
+//
+void
+pool_reregister (DebugPoolTy *Pool,
+                 void * newptr,
+                 void * oldptr,
+                 unsigned NumBytes) {
+  if (oldptr == NULL) {
+    //
+    // If the old pointer is NULL, then we know that this is essentially a
+    // regular heap allocation; treat it as such.
+    //
+    pool_register (Pool, newptr, NumBytes);
+  } else if (NumBytes == 0) {
+    //
+    // Allocating a buffer of zero bytes is essentially a deallocation of the
+    // memory; treat it as such.
+    //
+    pool_unregister (Pool, oldptr);
+  } else {
+    //
+    // Otherwise, this is a true reallocation.  Unregister the old memory and
+    // register the new memory.
+    pool_unregister (Pool, oldptr);
+    pool_register(Pool, newptr, NumBytes);
+  }
+
+  return;
+}
+
+void
+pool_reregister_debug (DebugPoolTy *Pool,
+                       void * newptr,
+                       void * oldptr,
+                       unsigned NumBytes,
+                       TAG,
+                       const char * SourceFilep,
+                       unsigned lineno) {
+  if (oldptr == NULL) {
+    //
+    // If the old pointer is NULL, then we know that this is essentially a
+    // regular heap allocation; treat it as such.
+    //
+    pool_register_debug (Pool, newptr, NumBytes, tag, SourceFilep, lineno);
+  } else if (NumBytes == 0) {
+    //
+    // Allocating a buffer of zero bytes is essentially a deallocation of the
+    // memory; treat it as such.
+    //
+    pool_unregister_debug (Pool, oldptr, tag, SourceFilep, lineno);
+  } else {
+    //
+    // Otherwise, this is a true reallocation.  Unregister the old memory and
+    // register the new memory.
+    pool_unregister_debug (Pool, oldptr, tag, SourceFilep, lineno);
+    pool_register_debug   (Pool, newptr, NumBytes, tag, SourceFilep, lineno);
+  }
+
+  return;
+}
+
+//
+// Function: poolregister_stack_debug()
+//
+// Description:
+//  This function is externally visible and is called by code to register
+//  a stack allocation.
+//
+void
+pool_register_stack_debug (DebugPoolTy *Pool,
+                           void * allocaptr,
+                           unsigned NumBytes, TAG,
+                           const char * SourceFilep,
+                           unsigned lineno) {
+  //
+  // Use the common registration function.  Mark the allocation as a stack
+  // allocation.
+  //
+  _internal_poolregister (Pool,
+                          allocaptr,
+                          NumBytes, tag,
+                          SourceFilep,
+                          lineno,
+                          Stack);
+
+  //
+  // Create the meta data object containing the debug information for this
+  // pointer.
+  //
+  PDebugMetaData debugmetadataPtr;
+  debugmetadataPtr = createPtrMetaData (0,
+                                        0,
+                                        Stack,
+                                        __builtin_return_address(0),
+                                        0,
+                                        getCanonicalPtr(allocaptr),
+                                        (const char *) SourceFilep, lineno);
+  dummyPool.DPTree.insert (allocaptr,
+                           (char*) allocaptr + NumBytes - 1,
+                           debugmetadataPtr);
+
+}
+
+//
+// Function: poolregister_stack()
+//
+// Description:
+//  This function is externally visible and is called by code to register
+//  a stack allocation without debug information.
+//
+void
+pool_register_stack (DebugPoolTy *Pool, void * allocaptr, unsigned NumBytes) {
+  //
+  // Use the common registration function.  Mark the allocation as a stack
+  // allocation.
+  //
+  _internal_poolregister (Pool,
+                          allocaptr,
+                          NumBytes, 0,
+                          "<Unknown>",
+                          0,
+                          Stack);
+}
+
+//
+// Function: __sc_dbg_src_poolregister_global()
+//
+// Description:
+//  This function is externally visible and is called by code to register
+//  a global variable.
+//
+void
+pool_register_global (DebugPoolTy *Pool, void * allocaptr, unsigned NumBytes) {
+  //
+  // Use the common registration function.  Mark the allocation as a stack
+  // allocation.
+  //
+  _internal_poolregister (Pool,
+                          allocaptr,
+                          NumBytes,
+                          0,
+                          "<unknown>",
+                          0,
+                          Global);
+}
+
+//
+// Function: __sc_dbg_src_poolregister_global_debug()
+//
+// Description:
+//  This function is externally visible and is called by code to register
+//  a global variable with debugging information attached.
+//
+void
+pool_register_global_debug (DebugPoolTy *Pool,
+                            void * allocaptr,
+                            unsigned NumBytes, TAG,
+                            const char * SourceFilep,
+                            unsigned lineno) {
+  //
+  // Use the common registration function.  Mark the "allocation" as a global
+  // object.
+  //
+  _internal_poolregister (Pool,
+                          allocaptr,
+                          NumBytes, tag,
+                          SourceFilep,
+                          lineno,
+                          Global);
+
+  //
+  // Create the meta data object containing the debug information for this
+  // pointer.
+  //
+  PDebugMetaData debugmetadataPtr;
+  debugmetadataPtr = createPtrMetaData (0,
+                                        0,
+                                        Global,
+                                        __builtin_return_address(0),
+                                        0,
+                                        getCanonicalPtr(allocaptr),
+                                        (const char *) SourceFilep, lineno);
+  dummyPool.DPTree.insert (allocaptr,
+                           (char*) allocaptr + NumBytes - 1,
+                           debugmetadataPtr);
+
+}
+
+//
+// Function: checkForBadFrees()
+//
+// Description:
+//  This function can be called by pool_unregister() functions to determine if
+//  an invalid free is being performed.
+//
+static inline void
+checkForBadFrees (DebugPoolTy *Pool,
+                  void * allocaptr, allocType Type,
+                  unsigned tag,
+                  const char * SourceFilep,
+                  unsigned lineno) {
+  //
+  // Increment the ID number for this deallocation.
+  //
+  unsigned freeID = (freeSeqMap[tag] += 1);
+
+  //
+  // Ignore frees of NULL pointers.  These are okay.
+  //
+  if (allocaptr == NULL)
+    return;
+
+  //
+  // Retrieve the debug information about the node.  This will include a
+  // pointer to the canonical page.
+  //
+  void * start;
+  void * end;
+  PDebugMetaData debugmetadataptr = 0;
+  bool found = dummyPool.DPTree.find (allocaptr, start, end, debugmetadataptr);
+
+  // Assert that we either didn't find the object or we found the object *and*
+  // it has meta-data associated with it.
+  assert ((!found || (found && debugmetadataptr)) &&
+          "checkForBadFrees: No debugmetadataptr\n");
+
+  //
+  // If we cannot find the meta-data for this pointer, then the free is
+  // invalid.  Report it as an error and then continue executing if possible.
+  //
+  if (!found) {
+    DebugViolationInfo v;
+    v.type = DebugViolationInfo::FAULT_INVALID_FREE,
+      v.faultPC = __builtin_return_address(0),
+      v.faultPtr = allocaptr;
+      v.PoolHandle = Pool;
+      v.dbgMetaData = debugmetadataptr;
+      v.SourceFile = SourceFilep;
+      v.lineNo = lineno;
+    ReportMemoryViolation(&v);
+    return;
+  }
+
+  //
+  // Update the debugging metadata information for this object.
+  //
+  updatePtrMetaData (debugmetadataptr,
+                     freeID,
+                     __builtin_return_address(0),
+                     (void *)SourceFilep,
+                     lineno);
+
+  //
+  // Determine if we are doing something stupid like deallocating a global
+  // or stack-allocated object when we're supposed to be freeing a heap
+  // object.  If so, then report an error.
+  //
+  if (Type == Heap) {
+    if (debugmetadataptr->allocationType != Heap) {
+        DebugViolationInfo v;
+        v.type = ViolationInfo::FAULT_NOTHEAP_FREE,
+        v.faultPC = __builtin_return_address(0);
+        v.PoolHandle = Pool;
+        v.dbgMetaData = debugmetadataptr;
+        v.SourceFile = SourceFilep;
+        v.lineNo = lineno;
+        v.faultPtr = allocaptr;
+        ReportMemoryViolation(&v);
+    }
+  }
+
+  //
+  // Determine if we're freeing a pointer that doesn't point to the beginning
+  // of an object.  If so, report an error.
+  //
+  if (allocaptr != start) {
+    OutOfBoundsViolation v;
+    v.type = ViolationInfo::FAULT_INVALID_FREE,
+      v.faultPC = __builtin_return_address(0),
+      v.faultPtr = allocaptr,
+      v.dbgMetaData = debugmetadataptr,
+      v.SourceFile = SourceFilep,
+      v.lineNo = lineno,
+      v.objStart = start;
+      v.objLen =  (intptr_t)end - (intptr_t)start + 1;
+    ReportMemoryViolation(&v);
+    return;
+  }
+
+  //
+  // If dangling pointer detection is not enabled, remove the object from the
+  // dangling pointer splay tree.  The memory object's virtual address will be
+  // reused, and we don't want to match it for subsequently allocated objects.
+  //
+  // Also, always remove stack objects.  Their virtual addresses are recycled,
+  // and so we don't want to try to re-look up their old start and end values.
+  //
+  if ((Type == Stack) || (!(ConfigData.RemapObjects))) {
+    free (debugmetadataptr);
+    dummyPool.DPTree.remove (allocaptr);
+  }
+
+  return;
+}
+
+//
+// Function: poolunregister()
+//
+// Description:
+//  Remove the specified object from the set of valid objects in the Pool.
+//
+// Inputs:
+//  Pool      - The pool in which the object should belong.
+//  allocaptr - A pointer to the object to remove.  It can be NULL.
+//
+// Notes:
+//  Note that this function currently deallocates debug information about the
+//  allocation.  This is safe because this function is only called on stack
+//  objects.  This is less-than-ideal because we lose debug information about
+//  the allocation of the stack object if it is later dereferenced outside its
+//  function (dangling pointer), but it is currently too expensive to keep that
+//  much debug information around.
+//
+// TODO: The above note is no longer correct; this function is called for stack
+//       and heap allocated objects.  A parameter flags whether the object is
+//       a heap object or a stack/global object.
+//
+static inline void
+_internal_poolunregister (DebugPoolTy *Pool,
+                          void * allocaptr, allocType Type,
+                          unsigned tag,
+                          const char * SourceFilep,
+                          unsigned lineno) {
+  if (logregs) {
+    fprintf (stderr, "pool_unregister: Start: %p: %s %d\n", allocaptr, SourceFilep, lineno);
+    fflush (stderr);
+  }
+
+  //
+  // For the NULL pointer, we take no action but flag no error.
+  //
+  if (!allocaptr) return;
+
+  //
+  // If there was no pool specified, use the splay tree associated with
+  // externally allocated objects.
+  //
+  RangeSplaySet<> * SPTree = (Pool ? &(Pool->Objects) : ExternalObjects);
+
+  //
+  // Remove the object from the pool's splay tree.
+  //
+  SPTree->remove (allocaptr);
+
+  //
+  // Eject the pointer from the pool's cache if necessary.
+  //
+  if (Pool) {
+    if ((Pool->objectCache[0].lower <= allocaptr) &&
+        (allocaptr <= Pool->objectCache[0].upper))
+      Pool->objectCache[0].lower = Pool->objectCache[0].upper = 0;
+
+    if ((Pool->objectCache[1].lower <= allocaptr) &&
+        (allocaptr <= Pool->objectCache[1].upper))
+      Pool->objectCache[1].lower = Pool->objectCache[1].upper = 0;
+  }
+
+  //
+  // Generate some debugging output.
+  //
+  if (logregs) {
+    fprintf (stderr, "pool_unregister: Done: %p: %s %d\n", allocaptr, SourceFilep, lineno);
+    fflush (stderr);
+  }
+}
+
+void
+pool_unregister (DebugPoolTy *Pool, void * allocaptr) {
+  _internal_poolunregister (Pool, allocaptr, Heap, 0, "Unknown", 0);
+  return;
+}
+
+void
+pool_unregister_debug (DebugPoolTy *Pool,
+                       void * allocaptr,
+                       TAG,
+                       const char * SourceFilep,
+                       unsigned lineno) {
+  checkForBadFrees (Pool, allocaptr, Heap, tag, SourceFilep, lineno);
+  _internal_poolunregister (Pool, allocaptr, Heap, tag, SourceFilep, lineno);
+  return;
+}
+
+void
+pool_unregister_stack (DebugPoolTy *Pool, void * allocaptr) {
+  _internal_poolunregister (Pool, allocaptr, Stack, 0, "Unknown", 0);
+  return;
+}
+
+void
+pool_unregister_stack_debug (DebugPoolTy *Pool,
+                                     void * allocaptr,
+                                     TAG,
+                                     const char * SourceFilep,
+                                     unsigned lineno) {
+  checkForBadFrees (Pool, allocaptr, Stack, tag, SourceFilep, lineno);
+  _internal_poolunregister (Pool, allocaptr, Stack, tag, SourceFilep, lineno);
+  return;
+}
+
+//
+// Function: poolalloc_debug()
+//
+// Description:
+//  This function is just like poolalloc() except that it associates a source
+//  file and line number with the allocation.
+//
+void *
+__sc_dbg_src_poolalloc (DebugPoolTy *Pool,
+                        unsigned NumBytes, TAG,
+                        const char * SourceFilep,
+                        unsigned lineno) {
+  //
+  // Ensure that we're allocating at least one byte.
+  //
+  if (NumBytes == 0) NumBytes = 1;
+
+  // Perform the allocation and determine its offset within the physical page.
+  void * canonptr = __pa_bitmap_poolalloc(Pool, NumBytes);
+  return canonptr;
+}
+
+//
+// Function: poolfree_debug()
+//
+// Description:
+//  This function is identical to poolfree() except that it relays source-level
+//  debug information to the error reporting routines.
+//
+void
+__sc_dbg_src_poolfree (DebugPoolTy *Pool,
+                       void * Node, TAG,
+                       const char * SourceFile,
+                       unsigned int lineno) {
+  //
+  // Free the object within the pool; the poolunregister() function will
+  // detect invalid frees.
+  //
+  __pa_bitmap_poolfree (Pool, Node);
+}
+
+
+//===----------------------------------------------------------------------===//
+//
+// Dangling pointer runtime functions
+//
+//===----------------------------------------------------------------------===//
+
+//
+// Function: createPtrMetaData()
+//  Allocates memory for a DebugMetaData struct and fills up the appropriate
+//  fields so to keep a record of the pointer's meta data
+//
+// Inputs:
+//  AllocID        - A unique identifier for the allocation.
+//  FreeID         - A unique identifier for the deallocation.
+//  allocationType - The type of allocation.
+//  AllocPC        - The program counter at which the object was allocated.
+//  FreePC         - The program counter at which the object was freed.
+//  Canon          - The canonical address of the memory object.
+//
+static PDebugMetaData
+createPtrMetaData (unsigned AllocID,
+                   unsigned FreeID,
+                   allocType allocationType,
+                   void * AllocPC,
+                   void * FreePC,
+                   void * Canon,
+                   const char * SourceFile,
+                   unsigned lineno) {
+  // FIXME:
+  //  This will cause an allocation that is registered as an external
+  //  allocation.  We need to use some internal allocation routine.
+  //
+  PDebugMetaData ret = (PDebugMetaData) malloc (sizeof(DebugMetaData));
+  ret->allocID = AllocID;
+  ret->freeID = FreeID;
+  ret->allocPC = AllocPC;
+  ret->freePC = FreePC;
+  ret->canonAddr = Canon;
+  ret->SourceFile = SourceFile;
+  ret->lineno = lineno;
+  ret->allocationType = allocationType;
+
+  ret->FreeSourceFile = 0;
+  ret->Freelineno = 0;
+  return ret;
+}
+
+static inline void
+updatePtrMetaData (PDebugMetaData debugmetadataptr,
+                   unsigned freeID,
+                   void * paramFreePC,
+                   void * SourceFile,
+                   unsigned lineno) {
+  debugmetadataptr->freeID = freeID;
+  debugmetadataptr->freePC = paramFreePC;
+  debugmetadataptr->FreeSourceFile = SourceFile;
+  debugmetadataptr->Freelineno = lineno;
+  return;
+}
+
+//
+// Function: getProgramCounter()
+//
+// Description:
+//  This function determines the program counter at which a fault was taken.
+//
+// Inputs:
+//  context - A pointer to the context in which the fault occurred.  This is
+//            a paramter that is passed into signal handlers.
+//
+// Return value:
+//  0  - The program counter could not be determined on this platform.
+//  ~0 - Otherwise, the program counter at which the fault occurred is
+//       returned.
+//
+static uintptr_t
+getProgramCounter (void * context) {
+#if defined(__APPLE__)
+#if defined(i386) || defined(__i386__) || defined(__x86__)
+  // Cast parameters to the desired type
+  ucontext_t * mycontext = (ucontext_t *) context;
+  return (mycontext->uc_mcontext->__ss.__eip);
+#endif
+
+#if defined(__x86_64__)
+  // Cast parameters to the desired type
+  ucontext_t * mycontext = (ucontext_t *) context;
+  return (mycontext->uc_mcontext->__ss.__rip);
+#endif
+#endif
+
+#if defined(__linux__)
+  // Cast parameters to the desired type
+  ucontext_t * mycontext = (ucontext_t *) context;
+  return (mycontext->uc_mcontext.gregs[14]);
+#endif
+
+  return 0;
+}
+
+//
+// Function: bus_error_handler()
+//
+// Description:
+//  This is the signal handler that catches bad memory references.
+//
+static void
+bus_error_handler (int sig, siginfo_t * info, void * context) {
+  if (1) {
+    fprintf (stderr, "SAFECode: Fault!\n");
+    fflush (stderr);
+  }
+
+  //
+  // Disable the signal handler for now.  If this function does something
+  // wrong, we want the bus error to terminate the program.
+  //
+  signal(SIGBUS, NULL);
+
+  //
+  // Get the program counter for where the fault occurred.
+  //
+  uintptr_t program_counter = getProgramCounter (context);
+
+  //
+  // Get the address causing the fault.
+  //
+  void * faultAddr = info->si_addr, *end;
+  PDebugMetaData debugmetadataptr;
+  int fs = 0;
+
+  //
+  // If the faulting pointer is within the zero page or the reserved memory
+  // region for uninitialized variables, then report an error.
+  //
+#if defined(__linux__)
+  const unsigned lowerUninit = 0xc0000000u;
+  const unsigned upperUninit = 0xffffffffu;
+#else
+  unsigned lowerUninit = 0x00000000u;
+  unsigned upperUninit = 0x00000fffu;
+#endif
+  if ((lowerUninit <= (uintptr_t)(faultAddr)) &&
+      ((uintptr_t)(faultAddr) <= upperUninit)) {
+    DebugViolationInfo v;
+    v.type = ViolationInfo::FAULT_UNINIT,
+      v.faultPC = (const void*) program_counter,
+      v.faultPtr = faultAddr,
+      v.dbgMetaData = 0;
+
+    ReportMemoryViolation(&v);
+    return;
+  }
+
+  //
+  // Attempt to look up dangling pointer information for the faulting pointer.
+  //
+  fs = dummyPool.DPTree.find (info->si_addr, faultAddr, end, debugmetadataptr);
+
+  //
+  // If there is no dangling pointer information for the faulting pointer,
+  // perhaps it is an Out of Bounds Rewrite Pointer.  Check for that now.
+  //
+  if (0 == fs) {
+    void * start = faultAddr;
+    void * tag = 0;
+    void * end;
+    if (OOBPool.OOB.find (faultAddr, start, end, tag)) {
+      const char * Filename = (const char *)(RewriteSourcefile[faultAddr]);
+      unsigned lineno = RewriteLineno[faultAddr];
+
+      //
+      // Get the bounds of the original object.
+      //
+      getOOBObject (faultAddr, start, end);
+      OutOfBoundsViolation v;
+      v.type = ViolationInfo::FAULT_LOAD_STORE,
+        v.faultPC = (const void*)program_counter,
+        v.faultPtr = tag,
+        v.dbgMetaData = NULL,
+        v.SourceFile = Filename,
+        v.lineNo = lineno,
+        v.objStart = start,
+        // FIXME: Make sure there is no off by one error in the line below
+        v.objLen = (char *)(end) - (char *)(start);
+
+      ReportMemoryViolation(&v);
+    } else {
+      //
+      // This is not a dangling pointer, uninitialized pointer, or a rewrite
+      // pointer.  This is some load/store that has obviously gone wrong (even
+      // if we consider the possibility of incompletenes).  Report it as a
+      // load/store error.
+      //
+      DebugViolationInfo v;
+      v.type = ViolationInfo::FAULT_LOAD_STORE,
+        v.faultPC = (const void*)program_counter,
+        v.faultPtr = faultAddr,
+        v.SourceFile = 0,
+        v.lineNo = 0;
+
+      ReportMemoryViolation(&v);
+    }
+
+    //
+    // Reinstall the signal handler for subsequent faults
+    //
+    struct sigaction sa;
+    sa.sa_sigaction = bus_error_handler;
+    sa.sa_flags = SA_SIGINFO;
+    if (sigaction(SIGBUS, &sa, NULL) == -1)
+      printf("sigaction installer failed!");
+    if (sigaction(SIGSEGV, &sa, NULL) == -1)
+      printf("sigaction installer failed!");
+
+    return;
+  }
+ 
+  // FIXME: Correct the semantics for calculating NumPPage 
+  unsigned NumPPage;
+  unsigned offset = (unsigned) ((long)info->si_addr & (PPageSize - 1) );
+  unsigned int len = (unsigned char *)(end) - (unsigned char *)(faultAddr) + 1;
+  NumPPage = (len / PPageSize) + 1;
+  if ( (len - (NumPPage-1) * PPageSize) > (PPageSize - offset) )
+    NumPPage++;
+ 
+  // This is necessary so that the program continues execution,
+  //  especially in debugging mode 
+  UnprotectShadowPage((void *)((long)info->si_addr & ~(PPageSize - 1)), NumPPage);
+  
+  //void* S = info->si_addr;
+  // printing reports
+  void * address = info->si_addr;
+
+  DebugViolationInfo v;
+    v.type = ViolationInfo::FAULT_DANGLING_PTR,
+      v.faultPC = (const void*) program_counter,
+    v.faultPtr = address,
+    v.dbgMetaData = debugmetadataptr;
+
+  ReportMemoryViolation(&v);
+
+  //
+  // Reinstall the signal handler for subsequent faults
+  //
+  struct sigaction sa;
+  sa.sa_sigaction = bus_error_handler;
+  sa.sa_flags = SA_SIGINFO;
+  if (sigaction(SIGBUS, &sa, NULL) == -1)
+    printf("sigaction installer failed!");
+  if (sigaction(SIGSEGV, &sa, NULL) == -1)
+    printf("sigaction installer failed!");
+  
+  return;
+}
+
+static void *
+getCanonicalPtr (void * ShadowPtr) {
+  //
+  // Look for the pointer in the dummy pool.  Assume that if it is not found,
+  // we will return the original shadow pointer.
+  //
+  void * start, * end;
+  void * CanonPtr = 0;
+  bool found = ShadowMap.find (ShadowPtr, start, end, CanonPtr);
+  return (found ? CanonPtr : ShadowPtr);
+}
+
+//
+// Function: pool_shadow()
+//
+// Description:
+//  Given the pointer to the beginning of an object, create a shadow object.
+//  This means that the physical memory is mapped to a new virtual address
+//  (i.e., the shadow address).  This shadow address is never re-used, so we
+//  can use it for dangling pointer detection.
+//
+// Inputs:
+//  CanonPtr - The pointer to remap.  This *must* be a pointer to the beginning
+//             of a heap object allocated by poolalloc().
+//  NumBytes - The size of the allocated object in bytes.
+//
+// Notes:
+//  This function does not do any sanity checking on its input.  Calls to it
+//  are added by the SAFECode transforms.  Therefore, there is no sanity
+//  checking on the input.
+//
+void *
+pool_shadow (void * CanonPtr, unsigned NumBytes) {
+  //
+  // Calculate the offset of the object from the beginning of the page.
+  //
+  uintptr_t offset = (((uintptr_t)(CanonPtr)) & (PPageSize-1));
+
+  //
+  // Remap the object, if necessary, and then calculate the pointer to the
+  // shadow object (RemapObject() returns the beginning of the page).
+  //
+  void * shadowpage = RemapObject (CanonPtr, NumBytes);
+  void * shadowptr = (unsigned char *)(shadowpage) + offset;
+
+  //
+  // Record the mapping from shadow pointer to canonical pointer.
+  //
+  ShadowMap.insert (shadowptr, 
+                        (char*) shadowptr + NumBytes - 1,
+                        CanonPtr);
+  if (logregs) {
+    fprintf (stderr, "pool_shadow: %p -> %p\n", CanonPtr, shadowptr);
+    fflush (stderr);
+  }
+  return shadowptr;
+}
+
+//
+// Function: pool_unshadow()
+//
+// Description:
+//  This function modifies the page protections of an object so that it is no
+//  longer writeable.
+//
+// Inputs:
+//  Node - A pointer to the beginning of the object that should be marked as
+//         read-only.
+//
+// Return value:
+//  The canonical version of the pointer is returned.  This value can be safely
+//  passed to poolfree().
+//
+// Notes:
+//  This function should only be called when dangling pointer detection is
+//  enabled.
+//
+void *
+pool_unshadow (void * Node) {
+  // The start and end of the object as registered in the dangling pointer
+  // object metapool
+  void * start = 0, * end = 0;
+
+  //
+  // Retrieve the debug information about the node.  This will include a
+  // pointer to the canonical page.
+  //
+  PDebugMetaData debugmetadataptr = 0;
+  bool found = dummyPool.DPTree.find (Node, start, end, debugmetadataptr);
+
+  // Assert that we either didn't find the object or we found the object *and*
+  // it has meta-data associated with it.
+  assert ((!found || (found && debugmetadataptr)) &&
+          "poolfree: No debugmetadataptr\n");
+
+  //
+  // If the object is not found, return.
+  //
+  if (!found) {
+    return Node;
+  }
+
+  if (logregs) {
+    fprintf (stderr, "pool_unshadow: Start: %p\n", Node);
+    fflush (stderr);
+  }
+
+  //
+  // Determine the number of pages that the object occupies.
+  //
+  ptrdiff_t len = (intptr_t)end - (intptr_t)start;
+  unsigned offset = (unsigned)((long)Node & (PPageSize - 1));
+  unsigned NumPPage = (len / PPageSize) + 1;
+  if ( (len - (NumPPage-1) * PPageSize) > (PPageSize - offset) )
+    NumPPage++;
+
+  if (logregs) {
+    fprintf (stderr, "pool_unshadow: Middle: %p\n", Node);
+    fflush (stderr);
+  }
+
+  // Protect the shadow pages of the object
+  ProtectShadowPage((void *)((long)Node & ~(PPageSize - 1)), NumPPage);
+  if (logregs) {
+    fprintf (stderr, "pool_unshadow: Done: %p\n", Node);
+    fflush (stderr);
+  }
+  return debugmetadataptr->canonAddr;
+}
+
+//
+// Function: poolcalloc_debug()
+//
+// Description:
+//  This is the same as pool_calloc but with source level debugging
+//  information.
+//
+// Inputs:
+//  Pool        - The pool from which to allocate the elements.
+//  Number      - The number of elements to allocate.
+//  NumBytes    - The size of each element in bytes.
+//  SourceFilep - A pointer to the source filename in which the caller is
+//                located.
+//  lineno      - The line number at which the call occurs in the source code.
+//
+// Return value:
+//  NULL - The allocation did not succeed.
+//  Otherwise, a fresh pointer to the allocated memory is returned.
+//
+// Notes:
+//  Note that this function calls poolregister() directly because the SAFECode
+//  transforms do not add explicit calls to poolregister().
+//
+void *
+__sc_dbg_src_poolcalloc (DebugPoolTy *Pool,
+                         unsigned Number,
+                         unsigned NumBytes, TAG,
+                         const char * SourceFilep,
+                         unsigned lineno) {
+  //
+  // Allocate the desired amount of memory.
+  //
+  void * New = __sc_dbg_src_poolalloc (Pool, Number * NumBytes, tag, SourceFilep, lineno);
+
+  //
+  // If the allocation succeeded, zero out the memory and do needed SAFECode
+  // operations.
+  //
+  if (New) {
+    // Zero the memory
+    bzero (New, Number * NumBytes);
+  }
+
+  //
+  // Print out some debugging information.
+  //
+  if (logregs) {
+    fprintf (ReportLog, "poolcalloc_debug: %p: %p %x: %s %d\n", (void*) Pool, (void*)New, Number * NumBytes, SourceFilep, lineno);
+    fflush (ReportLog);
+  }
+  return New;
+}
+
+void *
+__sc_dbg_poolcalloc (DebugPoolTy *Pool, unsigned Number, unsigned NumBytes) {
+  return __sc_dbg_src_poolcalloc (Pool, Number, NumBytes, 0, "<unknown>", 0);
+}
+
+void *
+__sc_dbg_poolrealloc (DebugPoolTy *Pool, void *Node, unsigned NumBytes) {
+  //
+  // If the object has never been allocated before, allocate it now, create a
+  // shadow object (if necessary), and register the object as a heap object.
+  //
+  if (Node == 0) {
+    void * New = __pa_bitmap_poolalloc(Pool, NumBytes);
+    if (ConfigData.RemapObjects) New = pool_shadow (New, NumBytes);
+    pool_register (Pool, New, NumBytes);
+    return New;
+  }
+
+  //
+  // Reallocate an object to 0 bytes means that we wish to free it.
+  //
+  if (NumBytes == 0) {
+    _internal_poolunregister (Pool, Node, Heap, 0, "Unknown", 0);
+    if (ConfigData.RemapObjects) Node = pool_unshadow (Node);
+    __pa_bitmap_poolfree(Pool, Node);
+    return 0;
+  }
+
+  //
+  // Otherwise, we need to change the size of the allocated object.  For now,
+  // we will simply allocate a new object and copy the data from the old object
+  // into the new object.
+  //
+
+  //
+  // Get the bounds of the old object.  If we cannot get the bounds, then
+  // simply fail the allocation.
+  //
+  void * S, * end;
+  if ((!(Pool->Objects.find (Node, S, end))) || (S != Node)) {
+    return 0;
+  }
+
+  //
+  // Allocate a new object.  If we fail, return NULL.
+  //
+  void *New;
+  if ((New = __pa_bitmap_poolalloc(Pool, NumBytes)) == 0)
+    return 0;
+
+  //
+  // Create a shadow of the new object (if necessary) and register it with the
+  // pool.
+  //
+  if (ConfigData.RemapObjects) New = pool_shadow (New, NumBytes);
+  pool_register (Pool, New, NumBytes);
+
+  //
+  // Determine the number of bytes to copy into the new object.
+  //
+  ptrdiff_t length = NumBytes;
+  if ((((uintptr_t)(end)) - ((uintptr_t)(S)) + 1) < NumBytes) {
+    length = ((intptr_t)(end)) - ((intptr_t)(S)) + 1;
+  }
+
+  //
+  // Copy the contents of the old object into the new object.
+  //
+  memcpy(New, Node, length);
+
+  //
+  // Invalidate the old object and its bounds and return the pointer to the
+  // new object.
+  //
+  _internal_poolunregister(Pool, Node, Heap, 0, "Unknown", 0);
+  if (ConfigData.RemapObjects) Node = pool_unshadow (Node);
+  __pa_bitmap_poolfree(Pool, Node);
+  return New;
+}
+
+void *
+__sc_dbg_poolrealloc_debug (DebugPoolTy *Pool,
+                            void *Node,
+                            unsigned NumBytes, TAG,
+                            const char * SourceFilep,
+                            unsigned lineno) {
+  //
+  // If the object has never been allocated before, allocate it now, create a
+  // shadow object (if necessary), and register the object as a heap object.
+  //
+  if (Node == 0) {
+    void * New = __pa_bitmap_poolalloc(Pool, NumBytes);
+    if (ConfigData.RemapObjects) New = pool_shadow (New, NumBytes);
+    pool_register_debug (Pool, New, NumBytes, tag, SourceFilep, lineno);
+    return New;
+  }
+
+  //
+  // Reallocate an object to 0 bytes means that we wish to free it.
+  //
+  if (NumBytes == 0) {
+    pool_unregister_debug (Pool, Node, tag, SourceFilep, lineno);
+    if (ConfigData.RemapObjects) Node = pool_unshadow (Node);
+    __pa_bitmap_poolfree(Pool, Node);
+    return 0;
+  }
+
+  //
+  // Otherwise, we need to change the size of the allocated object.  For now,
+  // we will simply allocate a new object and copy the data from the old object
+  // into the new object.
+  //
+
+  //
+  // Get the bounds of the old object.  If we cannot get the bounds, then
+  // simply fail the allocation.
+  //
+  void * S, * end;
+  if ((!(Pool->Objects.find (Node, S, end))) || (S != Node)) {
+    return 0;
+  }
+
+  //
+  // Allocate a new object.  If we fail, return NULL.
+  //
+  void *New;
+  if ((New = __pa_bitmap_poolalloc(Pool, NumBytes)) == 0)
+    return 0;
+
+  //
+  // Create a shadow of the new object (if necessary) and register it with the
+  // pool.
+  //
+  if (ConfigData.RemapObjects) New = pool_shadow (New, NumBytes);
+  pool_register_debug (Pool, New, NumBytes, tag, SourceFilep, lineno);
+
+  //
+  // Determine the number of bytes to copy into the new object.
+  //
+  ptrdiff_t length = NumBytes;
+  if ((((uintptr_t)(end)) - ((uintptr_t)(S)) + 1) < NumBytes) {
+    length = ((intptr_t)(end)) - ((intptr_t)(S)) + 1;
+  }
+
+  //
+  // Copy the contents of the old object into the new object.
+  //
+  memcpy(New, Node, length);
+
+  //
+  // Invalidate the old object and its bounds and return the pointer to the
+  // new object.
+  //
+  _internal_poolunregister(Pool, Node, Heap, tag, SourceFilep, lineno);
+  if (ConfigData.RemapObjects) Node = pool_unshadow (Node);
+  __pa_bitmap_poolfree(Pool, Node);
+  return New;
+}
+
+#if 0
+//
+// Function: internal_poolstrdup()
+//
+// Description:
+//  This is a pool allocated version of the strdup() function call.  It ensures
+//  that the object is properly registered in the correct pool.  This function
+//  contains common code for both the production and debug versions of the
+//  poolstrdup() function.
+//
+// Inputs:
+//  Pool        - The pool in which the new string should reside.
+//  Node        - The string which should be duplicated.
+//
+// Outputs:
+//  length      - The length of the memory object (in bytes) allocated by this
+//                function to hold the new string.
+// Return value:
+//  0 - The duplication failed.
+//  Otherwise, a pointer to the duplicated string is returned.
+//
+static void *
+internal_poolstrdup (DebugPoolTy * Pool,
+                     char * String,
+                     unsigned & length) {
+  //
+  // First determine the size of the string.  We use pool_strlen() to ensure
+  // that we do this safely.  Remember to increment the length by 1 to handle
+  // the fact that there is space for the string terminator byte.
+  //
+  extern size_t pool_strlen(DebugPoolTy *stringPool, const char *string, const unsigned char complete);
+  length = pool_strlen(Pool, String, 0) + 1;
+
+  //
+  // Now call the pool allocator's strdup() function.
+  //
+  void * Node = String;
+  void * NewNode = __pa_bitmap_poolstrdup (static_cast<BitmapPoolTy*>(Pool), Node);
+
+  if (NewNode) {
+    //
+    // Create a shadow copy of the object if dangling pointer detection is
+    // enabled.
+    //
+    if (ConfigData.RemapObjects)
+      NewNode = pool_shadow (NewNode, length);
+  }
+
+  return NewNode;
+}
+
+//
+// Function: poolstrdup()
+//
+// Description:
+//  This is a pool allocated version of the strdup() function call.  It ensures
+//  that the object is properly registered in the correct pool.
+//
+// Inputs:
+//  Pool        - The pool in which the new string should reside.
+//  Node        - The string which should be duplicated.
+//
+// Return value:
+//  0 - The duplication failed.
+//  Otherwise, a pointer to the duplicated string is returned.
+//
+void *
+__sc_dbg_poolstrdup (DebugPoolTy * Pool, char * Node) {
+  unsigned length = 0;
+  void * NewNode = internal_poolstrdup (Pool, Node, length);
+  if (NewNode) {
+    pool_register (Pool, NewNode, length);
+  }
+
+  return NewNode;
+}
+
+//
+// Function: poolstrdup_debug()
+//
+// Description:
+//  This is a pool allocated version of the strdup() function call.  It ensures
+//  that the object is properly registered in the correct pool.
+//
+// Inputs:
+//  Pool        - The pool in which the new string should reside.
+//  Node        - The string which should be duplicated.
+//  tag         - The tag associated with the call site.
+//  SourceFilep - The source file name in which the call site is located.
+//  lineno      - The source line number at which the call site is located.
+//
+// Return value:
+//  0 - The duplication failed.
+//  Otherwise, a pointer to the duplicated string is returned.
+//
+void *
+__sc_dbg_poolstrdup_debug (DebugPoolTy * Pool,
+                           char * Node,
+                           TAG,
+                           const char * SourceFilep,
+                           unsigned lineno) {
+  unsigned length = 0;
+  void * NewNode = internal_poolstrdup (Pool, Node, length);
+  if (NewNode) {
+    pool_register_debug (Pool,
+                         NewNode,
+                         length,
+                         tag,
+                         SourceFilep,
+                         lineno);
+  }
+
+  return NewNode;
+}
+#endif
+
+//
+// Function: poolinit()
+//
+// Description:
+//  Initialize a pool used in the debug run-time.
+//
+// Inputs:
+//  Pool - A pointer to the pool to initialize.
+//  NodeSize - The default size of an object allocated within the pool.
+//
+void *
+__sc_dbg_poolinit(DebugPoolTy *Pool, unsigned NodeSize, unsigned) {
+  //
+  // Create a record if necessary.
+  if (logregs) {
+    fprintf (stderr, "poolinit: %p %u\n", (void *) Pool, NodeSize);
+    fflush (stderr);
+  }
+
+  //
+  // Call the underlying allocator's poolinit() function to initialze the pool.
+  //
+  __pa_bitmap_poolinit(Pool, NodeSize);
+
+  //
+  // Call the in-place new operator for the splay tree of objects and, if
+  // applicable, the set of Out of Bound rewrite pointers and the splay tree
+  // used for dangling pointer detection.  This causes their constructors to
+  // be called on the already allocated memory.
+  //
+  // While this may appear odd, it is what we want.  The allocation of pools
+  // are added by the pool allocation transform.  Pools are either global
+  // variables (context insensitive) or stack allocated objects
+  // (context-sensitive).  Either way, their memory is not allocated by this
+  // run-time so in-place new operators must be used to initialize C++ classes
+  // within the pool.
+  //
+  new (&(Pool->Objects)) RangeSplaySet<>();
+  new (&(Pool->OOB)) RangeSplayMap<void *>();
+  new (&(Pool->DPTree)) RangeSplayMap<PDebugMetaData>();
+
+  //
+  // Initialize the object cache.
+  //
+  Pool->objectCache[0].lower = 0;
+  Pool->objectCache[0].upper = 0;
+  Pool->objectCache[1].lower = 0;
+  Pool->objectCache[1].upper = 0;
+  Pool->cacheIndex = 0;
+
+  return Pool;
+}
+
Index: runtime/libsc/DebugRuntime/DebugReport.h
===================================================================
--- runtime/libsc/DebugRuntime/DebugReport.h	(revision 0)
+++ runtime/libsc/DebugRuntime/DebugReport.h	(revision 0)
@@ -0,0 +1,62 @@
+//===- Report.h - Debugging reports for bugs found by SAFECode -*- C++ -*--===//
+// 
+//                       The SAFECode Compiler Project
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements functions for creating reports for the SAFECode
+// run-time.
+//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _DEBUG_REPORT_H_
+#define _DEBUG_REPORT_H_
+
+#include "../include/DebugRuntime.h"
+#include "../include/Report.h"
+
+namespace llvm {
+
+struct DebugViolationInfo : public ViolationInfo {
+  const DebugMetaData * dbgMetaData;
+  const void * PoolHandle;
+  const char * SourceFile;
+  unsigned int lineNo;
+  virtual void print (std::ostream & OS) const;
+  DebugViolationInfo() : dbgMetaData(0), SourceFile(0), lineNo(0) {}
+};
+
+struct OutOfBoundsViolation : public DebugViolationInfo {
+  //  objstart - The start of the object in which the source pointer was found.
+  //  objlen   - The length of the object in which the source pointer was found.
+  const void * objStart;
+  ptrdiff_t objLen;
+  virtual void print (std::ostream & OS) const;
+};
+
+struct AlignmentViolation : public OutOfBoundsViolation {
+  unsigned int alignment;
+  virtual void print (std::ostream & OS) const;
+};
+
+struct WriteOOBViolation : public DebugViolationInfo {
+  int copied;
+  int dstSize;
+  int srcSize;
+  virtual void print (std::ostream & OS) const;
+  WriteOOBViolation() : copied(-1), srcSize(-1) {}
+};
+
+struct CStdLibViolation : public DebugViolationInfo {
+  const char *function;
+  virtual void print (std::ostream & OS) const;
+  CStdLibViolation() : function(0) {}
+};
+
+}
+
+#endif
Index: runtime/libsc/DebugRuntime/CStdLib.h
===================================================================
--- runtime/libsc/DebugRuntime/CStdLib.h	(revision 0)
+++ runtime/libsc/DebugRuntime/CStdLib.h	(revision 0)
@@ -0,0 +1,314 @@
+//===------- CStdLib.h - CStdLib transform pass runtime helper functions -------===//
+// 
+//                          The SAFECode Compiler
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file provides all external functions included by the CStdLib pass.
+//
+//===--------------------------------------------------------------------------===//
+
+#ifndef _CSTDLIB_H
+#define _CSTDLIB_H
+
+#include "DebugReport.h"
+#include "PoolAllocator.h"
+
+#include <iostream>
+
+#define TAG unsigned tag
+#define SRC_INFO const char *SourceFile, unsigned lineNo
+
+// Default versions of arguments to debug functions
+#define DEFAULT_TAG 0
+#define DEFAULT_SRC_INFO "<Unknown>", 0
+#define SRC_INFO_ARGS SourceFile, lineNo
+
+using namespace llvm;
+
+namespace {
+
+  // Various violation types
+
+  inline void
+  OOB_VIOLATION(const void *fault_ptr,
+                DebugPoolTy *handle,
+                const void *start,
+                size_t len,
+                SRC_INFO) {
+    OutOfBoundsViolation v;
+    v.type        = ViolationInfo::FAULT_OUT_OF_BOUNDS;
+    v.faultPC     = __builtin_return_address(0);
+    v.faultPtr    = fault_ptr;
+    v.SourceFile  = SourceFile;
+    v.lineNo      = lineNo;
+    v.PoolHandle  = handle;
+    v.objStart    = start;
+    v.objLen      = len;
+    v.dbgMetaData = NULL;
+    ReportMemoryViolation(&v);
+  }
+
+  inline void
+  WRITE_VIOLATION(const void *fault_ptr,
+                  DebugPoolTy *handle,
+                  size_t dst_sz,
+                  size_t src_sz,
+                  SRC_INFO) {
+    WriteOOBViolation v;
+    v.type = ViolationInfo::FAULT_WRITE_OUT_OF_BOUNDS;
+    v.faultPC = __builtin_return_address(0); 
+    v.faultPtr = fault_ptr;
+    v.SourceFile = SourceFile;
+    v.lineNo =     lineNo;
+    v.PoolHandle = handle;
+    v.dstSize =    dst_sz;
+    v.srcSize =    src_sz;
+    v.dbgMetaData = NULL;
+    ReportMemoryViolation(&v);
+  }
+
+  inline void
+  LOAD_STORE_VIOLATION(const void *fault_ptr,
+                       DebugPoolTy *handle,
+                       SRC_INFO) {
+    DebugViolationInfo v;
+    v.faultPC = __builtin_return_address(0);
+    v.faultPtr = fault_ptr;
+    v.dbgMetaData = NULL;
+    v.PoolHandle = handle;
+    v.SourceFile = SourceFile;
+    v.lineNo = lineNo;
+    ReportMemoryViolation(&v);
+  }
+
+  inline void
+  C_LIBRARY_VIOLATION(const void *fault_ptr,
+                      DebugPoolTy *handle,
+                      const char *function,
+                      SRC_INFO) {
+    CStdLibViolation v;
+    v.type = ViolationInfo::FAULT_CSTDLIB;
+    v.faultPC = __builtin_return_address(0);
+    v.faultPtr = fault_ptr;
+    v.SourceFile = SourceFile;
+    v.lineNo     = lineNo;
+    v.PoolHandle = handle;
+    v.function   = function;
+    v.dbgMetaData = NULL;
+    ReportMemoryViolation(&v);
+  }
+
+
+  extern "C" {
+    inline size_t strnlen(const char *s, size_t maxlen) {
+      size_t i;
+      for (i = 0; i < maxlen && s[i]; ++i)
+        ;
+      return i;
+    }
+
+    inline size_t strnlen_opt(const char *s, size_t maxlen) {
+      const char *end = (const char *)memchr(s, '\0', maxlen);
+      return (end ? ((size_t) (end - s)) : maxlen);
+    }
+  }
+
+  /**
+   * Optimized inline assembly implementation of strncpy that returns the number
+   * of characters copied (including \0)
+   *
+   * @param   dst      Destination string pointer
+   * @param   src      Source string pointer
+   * @param   size     Number of characters to copy
+   * @return  Number of characters copied (including \0)
+   */
+  inline size_t
+  strncpy_asm(char *dst, const char *src, size_t size) {
+    long copied;
+
+  /*#if defined(i386) || defined(__i386__) || defined(__x86__)
+    __asm__ __volatile__(
+      "0: xorl      %%ecx, %%ecx      \n"
+      "   cmpl      %%edi, %%ecx      \n"
+      "   adcl      $0, %%ecx         \n"
+      "   decl      %%edi             \n"
+      "   testl     %%ecx, %%ecx      \n"
+      "   je        1f                \n"
+      "   movsbl    (%%edx), %%ecx    \n"
+      "   movb      %%cl, (%%eax)     \n"
+      "   incl      %%eax             \n"
+      "   incl      %%edx             \n"
+      "   testl     %%ecx, %%ecx      \n"
+      "   jne       0b                \n"
+      "1: subl      %%esi, %%eax      \n"
+      : "=a"(copied)
+      : "a"(dst), "S"(dst), "d"(src), "D"(size)
+      : "%ecx", "memory"
+    );
+  #else*/
+    strncpy(dst, src, size);
+    copied = strnlen(dst, size - 1);
+  //#endif
+
+    return copied;
+  }
+
+  /**
+   * Check for string termination.
+   *
+   * @param start  This is a pointer to the start of the string.
+   * @param end    The end of the object. String is not scanned farther than here.
+   * @param p      Reference to size object. Filled with the length of the string if
+   *               string is terminated, otherwised filled with the size of the object.
+   * @return       Returns true if the string is terminated within bounds (ie., 
+   *               if the nul terminator occurs between string and end, inclusive).
+   *               Returns false if no nul terminator was found.
+   *
+   * Note that start and end should be valid boundaries for a valid object.
+   */
+  inline bool
+  isTerminated(const char *start, void *end, size_t &p) {
+    size_t max = 1 + ((char *)end - (const char *)start), len;
+    len = strnlen((const char *)start, max);
+    p = len;
+    if (len == max)
+      return false;
+    else
+      return true;
+  }
+
+  /**
+   * Check for object overlap.
+   *
+   * @param ptr1Start  The start of the first memory object
+   * @param ptr1End    The end of the first memory object or the bound that writing
+   *                   operation actually touch.
+   * @param ptr2Start  The start of the second memory object
+   * @param ptr2End    The end of the second memory object or the bound that writing
+   *                   operation actually touch.
+   *
+   * @return           Whether these 2 memory object overlaps
+   */
+  inline bool
+  isOverlapped(const void* ptr1Start, 
+                           const void* ptr1End, 
+                           const void* ptr2Start, 
+                           const void* ptr2End){
+    if( ((long int)ptr1Start>(long int)ptr2End && (long int)ptr1End>(long int)ptr2Start) || 
+        ((long int)ptr1Start<(long int)ptr2End && (long int)ptr1End<(long int)ptr2Start)  )
+      return false;
+    return true;
+  }
+
+  /**
+   * Searches inside the given pool for the memory object associated with the
+   * the given address. If the memory object is found, it sets the poolBegin
+   * and poolEnd pointers to point to the first and last valid positions of
+   * the memory object, and returns true. If the memory object is not found in
+   * the pool, or the pool is NULL, it attemps to find the object in the external
+   * objects pool. When the object is not found in either pool, the function
+   * returns false.
+   *
+   * @param   pool       The pool handle which is expected to contain the object.
+   * @param   address    The address for which the bounding object is sought.
+   * @param   poolBegin  Reference to a pointer to set to the beginning of
+   *                     the memory object.
+   * @param   poolEnd    Reference to a pointer to set to the last valid address
+   *                     the memory object.
+   * @return  Returns true if the object was found, false otherwise.
+   */
+  inline bool
+  pool_find(DebugPoolTy *pool, void *address, void *&poolBegin, void *&poolEnd) {
+
+    if (address == NULL)
+      return false;
+
+    // Retrieve memory area's bounds from pool handle.
+    if ((pool && pool->Objects.find(address, poolBegin, poolEnd)) || 
+        ExternalObjects->find(address, poolBegin, poolEnd))
+      return true;
+
+    return false;
+  }
+
+  /* Macros for determining the completeness of pointer arguments using the
+     completeness bitwise vector. */
+  #define ARG1_COMPLETE(c) ((bool) (c & 0x1))
+  #define ARG2_COMPLETE(c) ((bool) (c & 0x2))
+
+  /**
+   * This function attempts to verify that given string pointer points to
+   * a valid string that is terminated within its memory object's boundaries.
+   * For strings that are marked complete, if the string is discovered to be
+   * not in its pool, or unterminated within memory object boundaries,
+   * the function reports a violation and returns false.
+   * For strings not marked complete, the function attempts to do the same
+   * checks as for complete pointers, except that it assumes the string was
+   * valid if the string's memory object is not found in the pool.
+   *
+   * The function returns true if no memory violations were discovered, and
+   * false when there was a violation.
+   *
+   * @param   string     The pointer to the string to be checked.
+   * @param   pool       The pool that should be searched for the memory object
+   *                     that contains the string.
+   * @param   complete   This is a boolean value which is true if the string
+   *                     pointer was reported complete by DSA, and false if not.
+   *                     If the string is incomplete, no errors are reported
+   *                     if it does not exist in the pool and is non-NULL.
+   * @param   function   The name of the C library function for debug reporting
+   *                     purposes.
+   * @param   SRC_INFO   Source and line info debug information.
+   * @return             Returns true if no violations were discoverd, and false
+   *                     if the pointer does not point to a valid string and a 
+   *                     memory violation was reported.
+   *                     Note that if the function returns true, the pointer may
+   *                     still not point to a valid string if the pointer was
+   *                     incomplete.
+   *
+   */
+  inline bool
+  validStringCheck(const char *string,
+                   DebugPoolTy *pool,
+                   bool complete,
+                   const char *function,
+                   SRC_INFO) {
+    void *objStart, *objEnd;
+    size_t len;
+
+    // Check if the string is NULL. If it is, report this as an error.
+    if (string == NULL) {
+      std::cout << "String pointer is NULL!\n";
+      C_LIBRARY_VIOLATION(string, pool, function, SRC_INFO_ARGS);
+      return false;
+    }
+
+    // Retrieve the string from the pool. If no string is found and the pointer
+    // is not complete, return true. Otherwise report an error and return false.
+    if (!pool_find(pool, (void *)string, objStart, objEnd)) {
+      if (complete) {
+        std::cout << "String not found in pool!\n";
+        LOAD_STORE_VIOLATION(string, pool, SRC_INFO_ARGS);
+        return false;
+      }
+      else
+        return true;
+    }
+
+    // Do a termination check.
+    if (!isTerminated(string, objEnd, len)) {
+      std::cout << "String is not terminated within object bounds!\n";
+      C_LIBRARY_VIOLATION(string, pool, function, SRC_INFO_ARGS);
+      return false;
+    }
+
+    return true;
+  }
+
+}
+
+#endif // _CSTDLIB_H
Index: runtime/libsc/DebugRuntime/README.txt
===================================================================
--- runtime/libsc/DebugRuntime/README.txt	(revision 0)
+++ runtime/libsc/DebugRuntime/README.txt	(revision 0)
@@ -0,0 +1,27 @@
+SafePoolAllocator is basically a safecode runtime which incorporates dangling
+pointer detection mechanism through the remapping of a virtual page for every
+memory object allocation. This also means that logically, without the recycling
+of virtual address, we can never see a same address appearing twice in the
+runtime of program compiled and linked with this runtime.
+
+
+The mechanism involved includes mach specific system calls, such as
+mach_vm_remap() used to remap multiple virtual pages to a physical page.
+In our current implementation, we also included extra data structure to
+keep track of memory allocation and deallocation metadata. This is done by a
+struct called DebugMetaData declared in PoolAllocator.h. Upon every memory
+object allocation, we allocate extra memory to support this structure.
+
+Upon deallocation, we utilize another system call, i.e. mprotect() to protect
+the virtual page which contains the memory object which was intended to be
+'freed'. Therefore, upon further reference to such page, the system will
+raise a fault, causing the SIG_BUS to be sent to the program.
+
+A signal handler is also written in this runtime in order to catch such signals.
+From there onwards, we search through the data structure to obtain the metadata
+we wanted. Then, we report this to the user.
+NOTE: The signal handler is system specific, i.e., x-86, to obtain information
+such as the PC currently faulting.
+
+Our current implementation may also face problems when compiled for 64-bit usage,
+only on the event of occurence of dangling error, as underlined by the NOTE above.
Index: runtime/libsc/DebugRuntime/Makefile
===================================================================
--- runtime/libsc/DebugRuntime/Makefile	(revision 0)
+++ runtime/libsc/DebugRuntime/Makefile	(revision 0)
@@ -0,0 +1,13 @@
+LEVEL = ../../..
+LIBRARYNAME=sc_dbg_rt
+#BYTECODE_LIBRARY=1
+
+ifeq ($(OS),Linux)
+CXX.Flags += -march=native
+else
+CXX.Flags += -march=nocona
+endif
+
+CXX.Flags += -fno-threadsafe-statics
+include $(LEVEL)/Makefile.common
+
Index: runtime/libsc/Makefile
===================================================================
--- runtime/libsc/Makefile	(revision 0)
+++ runtime/libsc/Makefile	(revision 0)
@@ -0,0 +1,15 @@
+##===- runtime/Makefile ------------------------------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+include $(LEVEL)/Makefile.config
+
+PARALLEL_DIRS  := BitmapPoolAllocator DebugRuntime
+
+include $(LEVEL)/Makefile.common
Index: runtime/Makefile
===================================================================
--- runtime/Makefile	(revision 135516)
+++ runtime/Makefile	(working copy)
@@ -12,7 +12,7 @@
 
 ifndef NO_RUNTIME_LIBS
 
-PARALLEL_DIRS  := libprofile
+PARALLEL_DIRS  := libprofile libsc
 
 # Disable libprofile: a faulty libtool is generated by autoconf which breaks the
 # build on Sparc
Index: tools/bugpoint/Makefile
===================================================================
--- tools/bugpoint/Makefile	(revision 135516)
+++ tools/bugpoint/Makefile	(working copy)
@@ -11,6 +11,6 @@
 TOOLNAME = bugpoint
 
 LINK_COMPONENTS := asmparser instrumentation scalaropts ipo \
-                   linker bitreader bitwriter
+                   linker bitreader bitwriter sc
 
 include $(LEVEL)/Makefile.common
Index: tools/opt/Makefile
===================================================================
--- tools/opt/Makefile	(revision 135516)
+++ tools/opt/Makefile	(working copy)
@@ -9,6 +9,7 @@
 LEVEL = ../..
 TOOLNAME = opt
 
-LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts ipo
+LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts \
+                   ipo sc
 
 include $(LEVEL)/Makefile.common
Index: lib/Transforms/MemSafety/RegisterBounds.cpp
===================================================================
--- lib/Transforms/MemSafety/RegisterBounds.cpp	(revision 0)
+++ lib/Transforms/MemSafety/RegisterBounds.cpp	(revision 0)
@@ -0,0 +1,641 @@
+//===- RegisterBounds.cpp ---------------------------------------*- C++ -*----//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// Various passes to register the bound information of variables into the pools
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "sc-register"
+
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/InstIterator.h"
+#include "llvm/Transforms/MemSafety/RegisterBounds.h"
+#include "llvm/Transforms/MemSafety/AllocatorInfo.h"
+#include "llvm/Transforms/MemSafety/Utility.h"
+
+#include <functional>
+
+using namespace llvm;
+
+namespace {
+  // Statistics
+  STATISTIC (RegisteredGVs,      "Number of registered global variables");
+  STATISTIC (RegisteredByVals,   "Number of registered byval arguments");
+  STATISTIC (RegisteredHeapObjs, "Number of registered heap objects");
+}
+
+namespace llvm {
+
+char RegisterGlobalVariables::ID = 0;
+char RegisterMainArgs::ID = 0;
+char RegisterFunctionByvalArguments::ID=0;
+char RegisterCustomizedAllocation::ID = 0;
+
+
+static llvm::RegisterPass<RegisterGlobalVariables>
+X1 ("reg-globals", "Register globals into pools", true);
+
+static llvm::RegisterPass<RegisterMainArgs>
+X2 ("reg-argv", "Register argv[] into pools", true);
+
+static llvm::RegisterPass<RegisterCustomizedAllocation>
+X3 ("reg-custom-alloc", "Register customized allocators", true);
+
+static llvm::RegisterPass<RegisterFunctionByvalArguments>
+X4 ("reg-byval-args", "Register byval arguments for functions", true);
+
+//
+// Method: registerGV()
+//
+// Description:
+//  This method adds code into a program to register a global variable into its
+//  pool.
+//
+void
+RegisterGlobalVariables::registerGV (GlobalVariable * GV,
+                                     Instruction * InsertBefore) {
+  // Don't bother to register external global variables
+  if (GV->isDeclaration()) {
+    return;
+  } 
+
+  //
+  // Get the pool into which the global should be registered.
+  //
+  Value * PH = ConstantPointerNull::get (getVoidPtrType(GV->getContext()));
+  Type* csiType = IntegerType::getInt32Ty(GV->getContext());
+  Type * GlobalType = GV->getType()->getElementType();
+  unsigned TypeSize = TD->getTypeAllocSize((GlobalType));
+  if (!TypeSize) {
+    llvm::errs() << "FIXME: Ignoring global of size zero: ";
+    GV->dump();
+    return;
+  }
+  Value * AllocSize = ConstantInt::get (csiType, TypeSize);
+  RegisterVariableIntoPool(PH, GV, AllocSize, InsertBefore);
+
+  // Update statistics
+  ++RegisteredGVs;
+}
+
+bool
+RegisterGlobalVariables::runOnModule(Module & M) {
+  init(M, "pool_register_global");
+
+  //
+  // Get required analysis passes.
+  //
+  TD       = &getAnalysis<TargetData>();
+
+  //
+  // Create a skeleton function that will register the global variables.
+  //
+  Type * VoidTy = Type::getVoidTy (M.getContext());
+  Constant * CF = M.getOrInsertFunction ("sc.register_globals", VoidTy, NULL);
+  Function * F = dyn_cast<Function>(CF);
+
+  //
+  // Create the basic registration function.
+  //
+  Instruction * InsertPt = CreateRegistrationFunction (F);
+
+  //
+  // Skip over several types of globals, including:
+  //  llvm.used
+  //  llvm.noinline
+  //  llvm.global_ctors
+  //  Any global pool descriptor
+  //  Any global in the meta-data seciton
+  //
+  // The llvm.global_ctors requires special note.  Apparently, it will not
+  // be code generated as the list of constructors if it has any uses
+  // within the program.  This transform must ensure, then, that it is
+  // never used, even if such a use would otherwise be innocuous.
+  //
+  Module::global_iterator GI = M.global_begin(), GE = M.global_end();
+  for ( ; GI != GE; ++GI) {
+    GlobalVariable *GV = dyn_cast<GlobalVariable>(GI);
+    if (!GV) continue;
+    std::string name = GV->getName();
+
+    // Skip globals in special sections
+    if ((GV->getSection()) == "llvm.metadata") continue;
+
+    if (strncmp(name.c_str(), "llvm.", 5) == 0) continue;
+    if (strncmp(name.c_str(), "__poolalloc", 11) == 0) continue;
+   
+    // Linking fails when registering objects in section exitcall.exit
+    // This is needed for the Linux kernel.
+    if (GV->getSection() == ".exitcall.exit") continue;
+
+    registerGV(GV, InsertPt);    
+  }
+
+  return true;
+}
+
+bool
+RegisterMainArgs::runOnModule(Module & M) {
+  init(M, "pool_register");
+  Function *MainFunc = M.getFunction("main");
+  if (MainFunc == 0 || MainFunc->isDeclaration()) {
+    return false;
+  }
+
+  if (MainFunc->arg_size() != 2) {
+    // No argc / argv, return
+    return false;
+  }
+
+  Function::arg_iterator AI = MainFunc->arg_begin();
+  Value *Argc = AI;
+  Value *Argv = ++AI;
+
+
+  Instruction * InsertPt = MainFunc->front().begin(); 
+
+  //
+  // FIXME:
+  //  This is a hack around what appears to be a DSA bug.  These pointers
+  //  should be marked incomplete, but for some reason, in at least one test
+  //  case, they are not.
+  //
+  // Register all of the argv strings
+  //
+  Type * VoidPtrType = getVoidPtrType(M.getContext());
+  Type * Int32Type = IntegerType::getInt32Ty(M.getContext());
+  Constant * CF = M.getOrInsertFunction ("poolargvregister",
+                                          getVoidPtrType(M.getContext()),
+                                          Int32Type,
+                                          PointerType::getUnqual (VoidPtrType),
+                                          NULL);
+  Function * RegisterArgv = dyn_cast<Function>(CF);
+
+  std::vector<Value *> fargs;
+  fargs.push_back (Argc);
+  fargs.push_back (Argv);
+  CallInst::Create (RegisterArgv, fargs, "", InsertPt);
+  return true;
+}
+
+
+///
+/// Methods for RegisterCustomizedAllocations
+///
+void
+RegisterCustomizedAllocation::proceedAllocator(Module * M, AllocatorInfo * info) {
+  Function * allocFunc = M->getFunction(info->getAllocCallName());
+  if (allocFunc) {
+    for (Value::use_iterator it = allocFunc->use_begin(), 
+           end = allocFunc->use_end(); it != end; ++it) {
+      if (CallInst * CI = dyn_cast<CallInst>(*it)) {
+        if (CI->getCalledValue() == allocFunc) {
+          registerAllocationSite(CI, info);
+          ++RegisteredHeapObjs;
+        }
+      }
+
+      //
+      // If the user is a constant expression, the constant expression may be
+      // a cast that is used by a call instruction.  Get the enclosing call
+      // instruction if so.
+      //
+      if (ConstantExpr * CE = dyn_cast<ConstantExpr>(*it)) {
+        if (CE->isCast()) {
+          for (Value::use_iterator iit = CE->use_begin(),
+                 end = CE->use_end(); iit != end; ++iit) {
+            if (CallInst * CI = dyn_cast<CallInst>(*iit)) {
+              if (CI->getCalledValue() == CE) {
+                registerAllocationSite(CI, info);
+                ++RegisteredHeapObjs;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  
+  //
+  // Find the deallocation function, visit all uses of it, and process all
+  // calls to it.
+  //
+  Function * freeFunc = M->getFunction(info->getFreeCallName());
+  if (freeFunc) {
+    for (Value::use_iterator it = freeFunc->use_begin(),
+           end = freeFunc->use_end(); it != end; ++it) {
+      if (CallInst * CI = dyn_cast<CallInst>(*it)) {
+        if (CI->getCalledValue() == freeFunc) {
+          registerFreeSite(CI, info);
+        }
+      }
+
+      //
+      // If the user is a constant expression, the constant expression may be
+      // a cast that is used by a call instruction.  Get the enclosing call
+      // instruction if so.
+      //
+      if (ConstantExpr * CE = dyn_cast<ConstantExpr>(*it)) {
+        if (CE->isCast()) {
+          for (Value::use_iterator iit = CE->use_begin(),
+                 end = CE->use_end(); iit != end; ++iit) {
+            if (CallInst * CI = dyn_cast<CallInst>(*iit)) {
+              if (CI->getCalledValue() == CE) {
+                registerFreeSite(CI, info);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+void
+RegisterCustomizedAllocation::proceedReallocator(Module * M, ReAllocatorInfo * info) {
+  Function * allocFunc = M->getFunction(info->getAllocCallName());
+  if (allocFunc) {
+    for (Value::use_iterator it = allocFunc->use_begin(), 
+           end = allocFunc->use_end(); it != end; ++it)
+      if (CallInst * CI = dyn_cast<CallInst>(*it)) {
+        registerReallocationSite(CI, info);
+        ++RegisteredHeapObjs;
+      }
+  }
+  
+  Function * freeFunc = M->getFunction(info->getFreeCallName());
+  if (freeFunc) {
+    for (Value::use_iterator it = freeFunc->use_begin(),
+           end = freeFunc->use_end(); it != end; ++it)
+      if (CallInst * CI = dyn_cast<CallInst>(*it))
+        registerFreeSite(CI, info);
+  }
+}
+
+bool
+RegisterCustomizedAllocation::runOnModule(Module & M) {
+  init(M, "pool_register");
+
+  //
+  // Ensure that a prototype for strlen() exists.
+  //
+  TargetData & TD = getAnalysis<TargetData>();
+  M.getOrInsertFunction ("strlen",
+                         TD.getIntPtrType(M.getContext()),
+                         getVoidPtrType(M.getContext()),
+                         NULL);
+
+  //
+  // Get the functions for reregistering and deregistering memory objects.
+  //
+  Type * Int32Type = IntegerType::getInt32Ty (M.getContext());
+  PoolReregisterFunc = (Function *) M.getOrInsertFunction ("pool_reregister",
+                                                           Type::getVoidTy (M.getContext()),
+                                                           getVoidPtrType (M),
+                                                           getVoidPtrType (M),
+                                                           getVoidPtrType (M),
+                                                           Int32Type,
+                                                           NULL);
+
+  Constant * CF = M.getOrInsertFunction ("pool_unregister",
+                                          Type::getVoidTy (M.getContext()),
+                                          getVoidPtrType(M.getContext()),
+                                          getVoidPtrType(M.getContext()),
+                                          NULL);
+  PoolUnregisterFunc = dyn_cast<Function>(CF);
+
+  AllocatorInfoPass & AIP = getAnalysis<AllocatorInfoPass>();
+  for (AllocatorInfoPass::alloc_iterator it = AIP.alloc_begin(),
+      end = AIP.alloc_end(); it != end; ++it) {
+    proceedAllocator(&M, *it);
+  }
+
+  for (AllocatorInfoPass::realloc_iterator it = AIP.realloc_begin(),
+      end = AIP.realloc_end(); it != end; ++it) {
+    proceedReallocator(&M, *it);
+  }
+
+  return true;
+}
+
+void
+RegisterCustomizedAllocation::registerAllocationSite(CallInst * AllocSite, AllocatorInfo * info) {
+  //
+  // Get the pool handle for the node.
+  //
+  LLVMContext & Context = AllocSite->getContext();
+  Value * PH = ConstantPointerNull::get (getVoidPtrType (Context));
+
+  BasicBlock::iterator InsertPt = AllocSite;
+  ++InsertPt;
+
+  Value * AllocSize = info->getOrCreateAllocSize(AllocSite);
+  if (!AllocSize->getType()->isIntegerTy(32)) {
+    AllocSize = CastInst::CreateIntegerCast (AllocSize,
+                                             Type::getInt32Ty(Context),
+                                             false,
+                                             AllocSize->getName(),
+                                             InsertPt);
+  }
+  RegisterVariableIntoPool (PH, AllocSite, AllocSize, InsertPt);
+}
+
+void
+RegisterCustomizedAllocation::registerReallocationSite(CallInst * AllocSite, ReAllocatorInfo * info) {
+  //
+  // Get the pool handle for the node.
+  //
+  LLVMContext & Context = AllocSite->getContext();
+  Value * PH = ConstantPointerNull::get (getVoidPtrType (Context));
+
+  //
+  // Find the instruction following the reallocation site; this will be where
+  // we insert the reallocation registration call.
+  //
+  BasicBlock::iterator InsertPt = AllocSite;
+  ++InsertPt;
+
+  //
+  // Get the size of the allocation and cast it to the desired type.
+  //
+  Value * AllocSize = info->getOrCreateAllocSize(AllocSite);
+  if (!AllocSize->getType()->isIntegerTy(32)) {
+    AllocSize = CastInst::CreateIntegerCast (AllocSize,
+                                             Type::getInt32Ty(Context),
+                                             false,
+                                             AllocSize->getName(),
+                                             InsertPt);
+  }
+
+  //
+  // Get the pointers to the old and new memory buffer.
+  //
+  Value * OldPtr = castTo (info->getAllocedPointer (AllocSite),
+                           getVoidPtrType(PH->getContext()),
+                           (info->getAllocedPointer (AllocSite))->getName(),
+                           InsertPt);
+  Value * NewPtr = castTo (AllocSite,
+                           getVoidPtrType(PH->getContext()),
+                           AllocSite->getName(),
+                           InsertPt);
+
+  //
+  // Create the call to reregister the allocation.
+  //
+  std::vector<Value *> args;
+  args.push_back (PH);
+  args.push_back (NewPtr);
+  args.push_back (OldPtr);
+  args.push_back (AllocSize);
+  CallInst::Create(PoolReregisterFunc, args, "", InsertPt); 
+  return;
+}
+
+void
+RegisterCustomizedAllocation::registerFreeSite (CallInst * FreeSite,
+                                                AllocatorInfo * info) {
+  //
+  // Get the pointer being deallocated.  Strip away casts as these may have
+  // been inserted after the DSA pass was executed and may, therefore, not have
+  // a pool handle.
+  //
+  Value * ptr = info->getFreedPointer(FreeSite)->stripPointerCasts();
+
+  //
+  // If the pointer is a constant NULL pointer, then don't bother inserting
+  // an unregister call.
+  //
+  if (isa<ConstantPointerNull>(ptr))
+    return;
+
+  //
+  // Get the pool handle for the freed pointer.
+  //
+  LLVMContext & Context = FreeSite->getContext();
+  Value * PH = ConstantPointerNull::get (getVoidPtrType(Context));
+
+  //
+  // Cast the pointer being unregistered and the pool handle into void pointer
+  // types.
+  //
+  Value * Casted = castTo (ptr,
+                           getVoidPtrType(Context),
+                           ptr->getName()+".casted",
+                           FreeSite);
+
+  Value * PHCasted = castTo (PH,
+                             getVoidPtrType(Context), 
+                             PH->getName()+".casted",
+                             FreeSite);
+
+  //
+  // Create a call that will unregister the object.
+  //
+  std::vector<Value *> args;
+  args.push_back (PHCasted);
+  args.push_back (Casted);
+  CallInst::Create (PoolUnregisterFunc, args, "", FreeSite);
+}
+
+Instruction *
+RegisterVariables::CreateRegistrationFunction(Function * F) {
+  //
+  // Destroy any code that currently exists in the function.  We are going to
+  // replace it.
+  //
+  destroyFunction (F);
+
+  //
+  // Add a call in the new constructor function to the SAFECode initialization
+  // function.
+  //
+  BasicBlock * BB = BasicBlock::Create (F->getContext(), "entry", F);
+
+  //
+  // Add a return instruction at the end of the basic block.
+  //
+  return ReturnInst::Create (F->getContext(), BB);
+}
+
+RegisterVariables::~RegisterVariables() {}
+
+//
+// Method: init()
+//
+// Description:
+//  This method performs some initialization that is common to all subclasses
+//  of this pass.
+//
+// Inputs:
+//  M            - The module in which to insert the function.
+//  registerName - The name of the function with which to register object.
+//
+void
+RegisterVariables::init (Module & M, std::string registerName) {
+  //
+  // Create the type of the registration function.
+  //
+  Type * Int8Type    = IntegerType::getInt8Ty(M.getContext());
+  Type * VoidTy      = Type::getVoidTy(M.getContext());
+
+  std::vector<Type *> ArgTypes;
+  ArgTypes.push_back (PointerType::getUnqual(Int8Type));
+  ArgTypes.push_back (PointerType::getUnqual(Int8Type));
+  ArgTypes.push_back (IntegerType::getInt32Ty(M.getContext()));
+  FunctionType * PoolRegTy = FunctionType::get (VoidTy, ArgTypes, false);
+
+  //
+  // Create the function.
+  //
+  PoolRegisterFunc = dyn_cast<Function>(M.getOrInsertFunction (registerName,
+                                                               PoolRegTy));
+  return;
+}
+
+void
+RegisterVariables::RegisterVariableIntoPool(Value * PH, Value * val, Value * AllocSize, Instruction * InsertBefore) {
+  if (!PH) {
+    llvm::errs() << "pool descriptor not present for " << val->getNameStr()
+                 << "\n";
+    return;
+  }
+
+  Value *GVCasted = castTo (val,
+                            getVoidPtrType(PH->getContext()), 
+                            val->getName()+".casted",
+                            InsertBefore);
+  Value * PHCasted = castTo (PH,
+                             getVoidPtrType(PH->getContext()), 
+                             PH->getName()+".casted",
+                             InsertBefore);
+  std::vector<Value *> args;
+  args.push_back (PHCasted);
+  args.push_back (GVCasted);
+  args.push_back (AllocSize);
+  CallInst::Create(PoolRegisterFunc, args, "", InsertBefore); 
+}
+
+bool
+RegisterFunctionByvalArguments::runOnModule(Module & M) {
+  init(M, "pool_register_stack");
+
+  //
+  // Fetch prerequisite analysis passes.
+  //
+  TD        = &getAnalysis<TargetData>();
+
+  //
+  // Insert required intrinsics.
+  //
+  Constant * CF = M.getOrInsertFunction ("pool_unregister_stack",
+                                          Type::getVoidTy (M.getContext()),
+                                          getVoidPtrType(M.getContext()),
+                                          getVoidPtrType(M.getContext()),
+                                          NULL);
+  StackFree = dyn_cast<Function>(CF);
+
+  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++ I) {
+    //
+    // Don't process declarations.
+    //
+    if (I->isDeclaration()) continue;
+
+    //
+    // Check the name of the function to see if it is a run-time function that
+    // we should not process.
+    //
+    if (I->hasName()) {
+      std::string Name = I->getName();
+      if ((Name.find ("__poolalloc") == 0) || (Name.find ("poolregister") == 0))
+        continue;
+    }
+
+    runOnFunction(*I);
+  }
+
+  return true;
+}
+
+//
+// Method: runOnFunction()
+//
+// Description:
+//  Entry point for this function pass.  This method will insert calls to
+//  register the memory allocated for the byval arguments passed into the
+//  specified function.
+//
+// Return value:
+//  true  - The function was modified.
+//  false - The function was not modified.
+//
+bool
+RegisterFunctionByvalArguments::runOnFunction (Function & F) {
+  //
+  // Scan through all arguments of the function.  For each byval argument,
+  // insert code to register the argument into its repspective pool.  Also
+  // record the mapping between argument and pool so that we can insert
+  // deregistration code at function exit.
+  //
+  typedef SmallVector<std::pair<Value*, Argument *>, 4> RegisteredArgTy;
+  RegisteredArgTy registeredArguments;
+  LLVMContext & Context = F.getContext();
+  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
+    if (I->hasByValAttr()) {
+      assert (isa<PointerType>(I->getType()));
+      PointerType * PT = cast<PointerType>(I->getType());
+      Type * ET = PT->getElementType();
+      Value * AllocSize = ConstantInt::get
+        (IntegerType::getInt32Ty(Context), TD->getTypeAllocSize(ET));
+      Value * PH = ConstantPointerNull::get (getVoidPtrType(Context));
+      Instruction * InsertBefore = &(F.getEntryBlock().front());
+      RegisterVariableIntoPool(PH, &*I, AllocSize, InsertBefore);
+      registeredArguments.push_back(std::make_pair<Value*, Argument*>(PH, &*I));
+    }
+  }
+
+  //
+  // Find all basic blocks which terminate the function.
+  //
+  SmallSet<BasicBlock *, 4> exitBlocks;
+  for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) {
+    if (isa<ReturnInst>(*I) || isa<UnwindInst>(*I)) {
+      exitBlocks.insert(I->getParent());
+    }
+  }
+
+  //
+  // At each function exit, insert code to deregister all byval arguments.
+  //
+  for (SmallSet<BasicBlock*, 4>::const_iterator BI = exitBlocks.begin(),
+                                                BE = exitBlocks.end();
+       BI != BE; ++BI) {
+    for (RegisteredArgTy::const_iterator I = registeredArguments.begin(),
+                                         E = registeredArguments.end();
+         I != E; ++I) {
+      SmallVector<Value *, 2> args;
+      Instruction * Pt = &((*BI)->back());
+      Value *CastPH  = castTo (I->first, getVoidPtrType(Context), Pt);
+      Value *CastV = castTo (I->second, getVoidPtrType(Context), Pt);
+      args.push_back (CastPH);
+      args.push_back (CastV);
+      CallInst::Create (StackFree, args, "", Pt);
+    }
+  }
+
+  //
+  // Update the statistics on the number of registered byval arguments.
+  //  
+  if (registeredArguments.size())
+    RegisteredByVals += registeredArguments.size();
+
+  return true;
+}
+
+}
Index: lib/Transforms/MemSafety/RewriteOOB.cpp
===================================================================
--- lib/Transforms/MemSafety/RewriteOOB.cpp	(revision 0)
+++ lib/Transforms/MemSafety/RewriteOOB.cpp	(revision 0)
@@ -0,0 +1,371 @@
+//===- RewriteOOB.cpp - Rewrite Out of Bounds Pointers -------------------- --//
+// 
+//                          The SAFECode Compiler 
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This pass performs necessary transformations to ensure that Out of Bound
+// pointer rewrites work correctly.
+//
+// TODO:
+//  There are several optimizations which may improve performance:
+//
+//  1) The old code did not insert calls to getActualValue() for pointers
+//     compared against a NULL pointer.  We should determine that this
+//     optimization is safe and re-enable it if it is safe.
+//
+//  2) We insert calls to getActualValue() even if the pointer is not checked
+//     by a bounds check (and hence, is never rewritten).  It's a bit tricky,
+//     but we should avoid rewriting a pointer back if its bounds check was
+//     removed because the resulting pointer was always used in comparisons.
+//
+//  3) If done properly, all loads and stores to type-unknown objects have a
+//     run-time check.  Therefore, we should only need OOB pointer rewriting on
+//     type-known memory objects.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "rewrite-OOB"
+
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Constants.h"
+#include "llvm/InstrTypes.h"
+#include "llvm/Instruction.h"
+#include "llvm/Instructions.h"
+#include "llvm/Support/InstIterator.h"
+#include "llvm/Transforms/MemSafety/RewriteOOB.h"
+#include "llvm/Transforms/MemSafety/Utility.h"
+
+#include <iostream>
+
+
+namespace llvm {
+
+// Identifier variable for the pass
+char RewriteOOB::ID = 0;
+
+// Statistics
+STATISTIC (Changes,    "Number of Bounds Checks Modified");
+STATISTIC (GetActuals, "Number of getActualValue() Calls Inserted");
+
+// Register the pass
+static RegisterPass<RewriteOOB> P ("oob-rewriter",
+                                   "OOB Pointer Rewrite Transform");
+
+//
+// Method: processFunction()
+//
+// Description:
+//  This method searches for calls to a specified run-time check.  For every
+//  such call, it replaces the pointer that the call checks with the return
+//  value of the call.
+//
+//  This allows functions like boundscheck() to return a rewrite pointer;
+//  this code changes the program to use the returned rewrite pointer instead
+//  of the original pointer which was passed into boundscheck().
+//
+// Inputs:
+//  M       - The module to modify.
+//  Check   - A reference to a structure describing the checking function to
+//            process.
+//
+// Return value:
+//  false - No modifications were made to the Module.
+//  true  - One or more modifications were made to the module.
+//
+bool
+RewriteOOB::processFunction (Module & M, const CheckInfo & Check) {
+  //
+  // Get a pointer to the checking function.  If the checking function does
+  // not exist within the program, then do nothing.
+  //
+  Function * F = M.getFunction (Check.name);
+  if (!F)
+    return false;
+
+  //
+  // Ensure the function has the right number of arguments and that its
+  // result is a pointer type.
+  //
+  assert (isa<PointerType>(F->getReturnType()));
+
+  //
+  // To avoid recalculating the dominator information each time we process a
+  // use of the specified function F, we will record the function containing
+  // the call instruction to F and the corresponding dominator information; we
+  // will then update this information only when the next use is a call
+  // instruction belonging to a different function.  We are helped by the fact
+  // that iterating through uses often groups uses within the same function.
+  //
+  Function * CurrentFunction = 0;
+  DominatorTree * domTree = 0;
+
+  //
+  // Iterate though all calls to the function and modify the use of the
+  // operand to be the result of the function.
+  //
+  bool modified = false;
+  for (Value::use_iterator FU = F->use_begin(); FU != F->use_end(); ++FU) {
+    //
+    // We are only concerned about call instructions; any other use is of
+    // no interest to the organization.
+    //
+    if (CallInst * CI = dyn_cast<CallInst>(*FU)) {
+      //
+      // We're going to make a change.  Mark that we will have done so.
+      //
+      modified = true;
+
+      //
+      // Get the operand that needs to be replaced as well as the operand
+      // with all of the casts peeled away.  Increment the operand index by
+      // one because a call instruction's first operand is the function to
+      // call.
+      //
+      Value * RealOperand = Check.getCheckedPointer (CI);
+      Value * PeeledOperand = RealOperand->stripPointerCasts();
+
+      //
+      // Cast the result of the call instruction to match that of the original
+      // value.
+      //
+      BasicBlock::iterator i(CI);
+      Instruction * CastCI = castTo (CI,
+                                     PeeledOperand->getType(),
+                                     PeeledOperand->getName(),
+                                     ++i);
+
+      //
+      // Get dominator information for the function.
+      //
+      if ((CI->getParent()->getParent()) != CurrentFunction) {
+        CurrentFunction = CI->getParent()->getParent();
+        domTree = &getAnalysis<DominatorTree>(*CurrentFunction);
+      }
+
+      //
+      // For every use that the call instruction dominates, change the use to
+      // use the result of the call instruction.  We first collect the uses
+      // that need to be modified before doing the modifications to avoid any
+      // iterator invalidation errors.
+      //
+      std::vector<User *> Uses;
+      Value::use_iterator UI = PeeledOperand->use_begin();
+      for (; UI != PeeledOperand->use_end(); ++UI) {
+        if (Instruction * Use = dyn_cast<Instruction>(*UI))
+          if ((CI != Use) && (domTree->dominates (CI, Use))) {
+            Uses.push_back (*UI);
+            ++Changes;
+          }
+      }
+
+      while (Uses.size()) {
+        User * Use = Uses.back();
+        Uses.pop_back();
+
+        Use->replaceUsesOfWith (PeeledOperand, CastCI);
+      }
+    }
+  }
+
+  return modified;
+}
+
+//
+// Method: addGetActualValues()
+//
+// Description:
+//  Search for comparison or pointer to integer cast instructions which will
+//  need to turn an OOB pointer back into the original pointer value.  Insert
+//  calls to getActualValue() to do the conversion.
+//
+// Inputs:
+//  M - The module in which to add calls to getActualValue().
+//
+// Return value:
+//  true  - The module was modified.
+//  false - The module was not modified.
+//
+bool
+RewriteOOB::addGetActualValues (Module & M) {
+  // Assume that we don't modify anything
+  bool modified = false;
+
+  for (Module::iterator F = M.begin(); F != M.end(); ++F) {
+    for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
+      if (ICmpInst *CmpI = dyn_cast<ICmpInst>(&*I)) {
+        assert ((CmpI->getNumOperands() == 2) &&
+                 "Compare instruction does not have two operands\n");
+        //
+        // Determine whether this is an integer comparison.
+        //
+        CmpInst::Predicate Pred = CmpI->getUnsignedPredicate();
+        if ((Pred >= CmpInst::FIRST_ICMP_PREDICATE) &&
+            (Pred <= CmpInst::LAST_ICMP_PREDICATE)) {
+          //
+          // Replace all pointer operands with a call to getActualValue().
+          // This will convert an OOB pointer back into the real pointer value.
+          //
+          if (isa<PointerType>(CmpI->getOperand(0)->getType())) {
+            // Rewrite both operands and flag that we modified the code
+            addGetActualValue(CmpI, 0);
+            modified = true;
+          }
+
+          if (isa<PointerType>(CmpI->getOperand(1)->getType())) {
+            // Rewrite both operands and flag that we modified the code
+            addGetActualValue(CmpI, 1);
+            modified = true;
+          }
+        }
+      }
+
+      if (PtrToIntInst * CastInst = dyn_cast<PtrToIntInst>(&*I)) {
+        //
+        // Replace all pointer operands with a call to getActualValue().
+        // This will convert an OOB pointer back into the real pointer value.
+        //
+        if (isa<PointerType>(CastInst->getOperand(0)->getType())) {
+          // Rewrite both operands and flag that we modified the code
+          addGetActualValue(CastInst, 0);
+          modified = true;
+        }
+      }
+    }
+  }
+
+  // Return whether we modified anything
+  return modified;
+}
+
+//
+// Method: addGetActualValue()
+//
+// Description:
+//  Insert a call to the getactualvalue() run-time function to convert the
+//  potentially Out of Bound pointer back into its original value.
+//
+// Inputs:
+//  SCI     - The instruction that has arguments requiring conversion.
+//  operand - The index of the operand to the instruction that requires
+//            conversion.
+//
+void
+RewriteOOB::addGetActualValue (Instruction *SCI, unsigned operand) {
+  //
+  // Get a reference to the getactualvalue() function.
+  //
+  Module * M = SCI->getParent()->getParent()->getParent();
+  Type * VoidPtrTy = getVoidPtrType (M->getContext());
+  Constant * GAVConst = M->getOrInsertFunction ("pchk_getActualValue",
+                                                VoidPtrTy,
+                                                VoidPtrTy,
+                                                VoidPtrTy,
+                                                NULL);
+  Function * GetActualValue = dyn_cast<Function>(GAVConst);
+
+  // We know that the operand is a pointer type 
+  Value *op   = SCI->getOperand(operand);
+
+  //
+  // Peel casts off of the operand.
+  //
+  Value * peeledOp = op->stripPointerCasts();
+
+  //
+  // Get the pool handle associated with the pointer.
+  //
+  Value *PH = 0;
+  if ((isa<Argument>(peeledOp)) || (isa<Instruction>(peeledOp))) {
+    PH = ConstantPointerNull::get (getVoidPtrType(peeledOp->getContext()));
+  } else if (isa<Constant>(peeledOp) || isa<AllocaInst>(peeledOp)) {
+    //
+    // FIXME:
+    //  Add a case for calls to heap allocation functions.
+    //
+    // Rewrite pointers are generated from calls to the SAFECode run-time
+    // checks.  Therefore, constants and return values from allocation
+    // functions are known to be the original value.
+    //
+    return;
+  }
+
+  //
+  // Create a call to getActualValue() to convert the pointer back to its
+  // original value.
+  //
+
+  //
+  // Update the number of calls to getActualValue() that we inserted.
+  //
+  ++GetActuals;
+
+  //
+  // Insert the call to getActualValue()
+  //
+  Type * VoidPtrType = getVoidPtrType(peeledOp->getContext());
+  Value * PHVptr = castTo (PH, VoidPtrType, "castPH", SCI);
+  Value * OpVptr = castTo (op,
+                           VoidPtrType,
+                           op->getName() + ".casted",
+                           SCI);
+
+  std::vector<Value *> args;
+  args.push_back (PHVptr);
+  args.push_back (OpVptr);
+  CallInst *CI = CallInst::Create (GetActualValue,
+                                   args,
+                                   "getval",
+                                   SCI);
+  Instruction *CastBack = castTo (CI,
+                                  op->getType(),
+                                  op->getName()+".castback",
+                                  SCI);
+  SCI->setOperand (operand, CastBack);
+}
+
+//
+// Method: runOnModule()
+//
+// Description:
+//  Entry point for this LLVM pass.
+//
+// Return value:
+//  true  - The module was modified.
+//  false - The module was not modified.
+//
+bool
+RewriteOOB::runOnModule (Module & M) {
+  //
+  // Insert calls so that comparison instructions convert Out of Bound pointers
+  // back into their original values.  This should be done *before* rewriting
+  // the program so that pointers are replaced with the return values of bounds
+  // checks; this is because the return values of bounds checks have no DSNode
+  // in the DSA results, and hence, no associated Pool Handle.
+  //
+  bool modified = addGetActualValues (M);
+
+  //
+  // Transform the code for each type of checking function.  Mark whether
+  // we've changed anything.
+  //
+  for (unsigned index = 0; index < numChecks; ++index) {
+    //
+    // If this is not a pointer arithmetic check, skip it.
+    //
+    if (!(RuntimeChecks[index].isMemcheck)) {
+      //
+      // Transform the function so that the pointer it checks is replaced with
+      // its return value.  The return value is the rewritten OOB pointer.
+      //
+      modified |= processFunction (M, RuntimeChecks[index]);
+    }
+  }
+  return modified;
+}
+
+}
+
Index: lib/Transforms/MemSafety/ExactCheckOpt.cpp
===================================================================
--- lib/Transforms/MemSafety/ExactCheckOpt.cpp	(revision 0)
+++ lib/Transforms/MemSafety/ExactCheckOpt.cpp	(revision 0)
@@ -0,0 +1,276 @@
+//===- ExactCheckOpt.cpp -------------------------------------------------- --//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+//  This pass tries to lower bounds checks and load/store checks to exact
+//  checks, that is checks whose bounds information can be determined easily,
+//  say, allocations inside a function or global variables. Therefore SAFECode
+//  does not need to register stuffs in the meta-data.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "exactcheck-opt"
+
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Transforms/MemSafety/AllocatorInfo.h"
+#include "llvm/Transforms/MemSafety/OptimizeChecks.h"
+#include "llvm/Transforms/MemSafety/Utility.h"
+
+#include <queue>
+
+namespace llvm {
+
+static RegisterPass<ExactCheckOpt> X ("exactcheck-opt", "Exact check optimization", true);
+
+// Pass Statistics
+namespace {
+  STATISTIC (ExactChecks ,    "The number of checks lowered to exactcheck");
+}
+
+char ExactCheckOpt::ID = 0;
+
+//
+// Method: runOnModule()
+//
+// Description:
+//  This method is the entry point for the transform pass.
+//
+// Inputs:
+//  M - The LLVM module to transform.
+//
+// Return value:
+//  true  - The module was modified.
+//  false - The module was not modified.
+//
+bool
+ExactCheckOpt::runOnModule(Module & M) {
+  //
+  // Add a prototype for the exactcheck function.
+  //
+  Type * VoidPtrTy = getVoidPtrType (M.getContext());
+  Type * Int32Type = IntegerType::getInt32Ty(M.getContext());
+  ExactCheck2 = (Function *) M.getOrInsertFunction ("exactcheck2",
+                                                    VoidPtrTy,
+                                                    VoidPtrTy,
+                                                    VoidPtrTy,
+                                                    Int32Type,
+                                                    NULL);
+
+  //
+  // Scan through all the intrinsics and process those that perform run-time
+  // checks.
+  //
+  for (unsigned index = 0; index < numChecks; ++index) {
+    //
+    // Clear the list of calls to intrinsics that must be removed.
+    //
+    checkingIntrinsicsToBeRemoved.clear();
+
+    //
+    // Scan through all uses of this run-time checking function and process
+    // each call to it.
+    //
+    Function * F = M.getFunction (RuntimeChecks[index].name);
+    if (F) {
+      for (Value::use_iterator UI = F->use_begin(), E = F->use_end();
+           UI != E;
+           ++UI) {
+        if (CallInst * CI = dyn_cast<CallInst>(*UI)) {
+          visitCheckingIntrinsic(CI, RuntimeChecks[index]);
+        }
+      }
+    }
+
+    //
+    // Update statistics if anything has changed.  We don't want to update
+    // the statistics variable if nothing has happened because we don't want
+    // it to appear in the output if it is zero.
+    //
+    if (checkingIntrinsicsToBeRemoved.size())
+      ExactChecks += checkingIntrinsicsToBeRemoved.size();
+
+    //
+    // Remove checking intrinsics that have been optimized
+    //
+    for (std::vector<CallInst*>::const_iterator i = checkingIntrinsicsToBeRemoved.begin(), e = checkingIntrinsicsToBeRemoved.end(); i != e; ++i) {
+      (*i)->eraseFromParent();
+    }
+  }
+
+  //
+  // Conservatively assume that we have changed something in the module.
+  //
+  return true;
+}
+
+//
+// Function: findObject()
+//
+// Description:
+//  Find the singular memory object to which this pointer points (if such a
+//  singular object exists and is easy to find).
+//
+static Value *
+findObject (Value * obj) {
+  std::set<Value *> exploredObjects;
+  std::set<Value *> objects;
+  std::queue<Value *> queue;
+
+  queue.push(obj);
+  while (!queue.empty()) {
+    Value * o = queue.front();
+    queue.pop();
+    if (exploredObjects.count(o)) continue;
+
+    exploredObjects.insert(o);
+
+    if (isa<CastInst>(o)) {
+      queue.push(cast<CastInst>(o)->getOperand(0));
+    } else if (isa<GetElementPtrInst>(o)) {
+      queue.push(cast<GetElementPtrInst>(o)->getPointerOperand());
+    } else if (isa<PHINode>(o)) {
+      PHINode * p = cast<PHINode>(o);
+      for(unsigned int i = 0; i < p->getNumIncomingValues(); ++i) {
+        queue.push(p->getIncomingValue(i));
+      }
+    } else {
+      objects.insert(o);
+    }
+  }
+  return objects.size() == 1 ? *(objects.begin()) : NULL;
+}
+
+//
+// Function: visitCheckingIntrinsic()
+//
+// Description:
+//  Attempts to rewrite an extensive check into an efficient, accurate array
+//  bounds check which will not use meta-data information.
+//
+// Inputs:
+//  CI    - A pointer to the instruction that performs a run-time check.
+//  Info  - A reference to a structure containing information on the
+//         run-time check.
+//
+// Return value:
+//  true  - Successfully rewrite the check into an exact check.
+//  false - Cannot perform the optimization.
+//
+bool
+ExactCheckOpt::visitCheckingIntrinsic (CallInst * CI, const struct CheckInfo & Info) {
+  //
+  // Get the pointer that is checked by this run-time check.
+  //
+  Value * CheckPtr = Info.getCheckedPointer(CI)->stripPointerCasts();
+
+  //
+  // Try to find the source of the pointer.
+  //
+  Value * BasePtr = findObject (CheckPtr);
+  if (!BasePtr) return false;
+
+  //
+  // If the call is to a memory checking function, then we cannot blindly
+  // convert a check that operates on a heap object; the heap object might be
+  // deallocated between the time it was allocated and the time of the check.
+  // Other checks can be converted since they don't try to detect dangling
+  // pointers.
+  //
+  // So, if this is a memory check, make sure that the object cannot be freed
+  // before the check.  Global variables and stack allocations cannot be freed.
+  //
+  if ((!(Info.isMemcheck)) ||
+      ((isa<AllocaInst>(BasePtr)) || isa<GlobalVariable>(BasePtr))) {
+    //
+    // Attempt to get the size of the pointer.  If a size is returned, we know
+    // that the base pointer points to the beginning of an object, and we can
+    // do a run-time check without a lookup.
+    //
+    AllocatorInfoPass & AIP = getAnalysis<AllocatorInfoPass>();
+    if (Value * Size = AIP.getObjectSize(BasePtr)) {
+      rewriteToExactCheck(CI, BasePtr, CheckPtr, Size);
+      return true;
+    }
+  }
+
+  //
+  // We were not able to insert a call to exactcheck().
+  //
+  return false;
+}
+
+//
+// Function: rewriteToExactCheck()
+//
+// Description:
+//  Rewrite a check into an exact check
+//
+// Inputs:
+//  BasePointer   - An LLVM Value representing the base of the object to check.
+//  Result        - An LLVM Value representing the pointer to check.
+//  Bounds        - An LLVM Value representing the bounds of the check.
+//
+void
+ExactCheckOpt::rewriteToExactCheck(CallInst * CI, Value * BasePointer, 
+                                   Value * ResultPointer, Value * Bounds) {
+  // The LLVM type for a void *
+  Type *VoidPtrType = getVoidPtrType(CI->getContext()); 
+  Type * Int32Type = IntegerType::getInt32Ty(CI->getContext());
+
+  //
+  // For readability, make sure that both the base pointer and the result
+  // pointer have names.
+  //
+  if (!(BasePointer->hasName())) BasePointer->setName("base");
+  if (!(ResultPointer->hasName())) ResultPointer->setName("result");
+
+  //
+  // Cast the operands to the correct type.
+  //
+  if (BasePointer->getType() != VoidPtrType)
+    BasePointer = castTo (BasePointer, VoidPtrType,
+                          BasePointer->getName()+".ec.casted",
+                          CI);
+
+  if (ResultPointer->getType() != VoidPtrType)
+    ResultPointer = castTo (ResultPointer, VoidPtrType,
+                            ResultPointer->getName()+".ec.casted",
+                            CI);
+
+  Value * CastBounds = Bounds;
+  if (Bounds->getType() != Int32Type) {
+    LLVMContext & Context = Int32Type->getContext();
+    CastBounds = CastInst::CreateIntegerCast (CastBounds,
+                                              Type::getInt32Ty(Context),
+                                              false,
+                                              CastBounds->getName(),
+                                              CI);
+  }
+
+  //
+  // Create the call to exactcheck2().
+  //
+  std::vector<Value *> args(1, BasePointer);
+  args.push_back(ResultPointer);
+  args.push_back(CastBounds);
+
+  CallInst * ExactCheckCI = CallInst::Create (ExactCheck2, args, "", CI);
+  // boundscheck / exactcheck return an out of bound pointer when REWRITE_OOB is
+  // enabled. We need to replace all uses to make the optimization correct, but
+  // we don't need do anything for load / store checks.
+  //
+  // We can test the condition above by simply testing the return types of the
+  // checking functions.
+  if (ExactCheckCI->getType() == CI->getType()) {
+    CI->replaceAllUsesWith(ExactCheckCI);
+  }
+
+  checkingIntrinsicsToBeRemoved.push_back(CI);
+}
+
+}
Index: lib/Transforms/MemSafety/DebugInstrumentation.cpp
===================================================================
--- lib/Transforms/MemSafety/DebugInstrumentation.cpp	(revision 0)
+++ lib/Transforms/MemSafety/DebugInstrumentation.cpp	(revision 0)
@@ -0,0 +1,450 @@
+//===- DebugInstrumentation.cpp - Modify run-time checks to track debug info -//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This pass modifies calls to the pool allocator and SAFECode run-times to
+// track source level debugging information.
+//
+// Notes:
+//  Some of this code is based off of code from the getLocationInfo() method in
+//  LLVM.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "debug-instrumentation"
+
+
+#include "llvm/Analysis/DebugInfo.h"
+#include "llvm/Constants.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Instructions.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/Metadata.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/InstIterator.h"
+#include "llvm/ADT/VectorExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
+#include "llvm/Transforms/MemSafety/DebugInstrumentation.h"
+#include "llvm/Transforms/MemSafety/Utility.h"
+
+#include <cstdlib>
+#include <iostream>
+#include <vector>
+
+using namespace llvm;
+
+namespace llvm {
+
+char DebugInstrument::ID = 0;
+
+// Register the pass
+static
+RegisterPass<DebugInstrument> X ("debuginstrument",
+                                 "Add Debug Data to SAFECode Run-Time Checks");
+
+static int tagCounter = 0;
+
+//
+// Basic LLVM Types
+//
+static Type * VoidType  = 0;
+static Type * Int8Type  = 0;
+static Type * Int32Type = 0;
+
+///////////////////////////////////////////////////////////////////////////
+// Command line options
+///////////////////////////////////////////////////////////////////////////
+
+namespace {
+  ///////////////////////////////////////////////////////////////////////////
+  // Pass Statistics
+  ///////////////////////////////////////////////////////////////////////////
+  STATISTIC (FoundSrcInfo,   "Number of Source Information Locations Found");
+  STATISTIC (QueriedSrcInfo, "Number of Source Information Locations Queried");
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Static Functions
+///////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////
+// Class Methods
+///////////////////////////////////////////////////////////////////////////
+
+GetSourceInfo::~GetSourceInfo() {}
+
+//
+// Method: operator()
+//
+// Description:
+//  Return the source information associated with the call instruction by
+//  finding the location within the source code in which the call is made.
+//
+// Inputs:
+//  CI - The call instruction
+//
+// Return value:
+//  A pair of LLVM values.  The first is the source file name; the second is
+//  the line number.  Default values are given if no source line information
+//  can be found.
+//
+std::pair<Value *, Value *>
+LocationSourceInfo::operator() (CallInst * CI) {
+  static int count=0;
+
+  //
+  // Update the number of source locations queried.
+  //
+  ++QueriedSrcInfo;
+
+  //
+  // Create default debugging values in case we don't find any debug
+  // information.  The filename becomes the function name (if the function
+  // has a name) and the line number becomes a unique identifier.
+  //
+  std::string filename = "<unknown>";
+  unsigned int lineno  = ++count;
+  if (CI->getParent()->getParent()->hasName())
+    filename = CI->getParent()->getParent()->getName();
+
+  //
+  // Get the line number and source file information for the call if it exists.
+  //
+  if (MDNode *Dbg = CI->getMetadata(dbgKind)) {
+    DILocation Loc (Dbg);
+    filename = Loc.getDirectory().str() + Loc.getFilename().str();
+    lineno   = Loc.getLineNumber();
+    ++FoundSrcInfo;
+  }
+
+  //
+  // Convert the source filename and line number information into LLVM values.
+  //
+  Value * LineNumber = ConstantInt::get (Int32Type, lineno);
+  Value * SourceFile;
+  if (SourceFileMap.find (filename) != SourceFileMap.end()) {
+    SourceFile = SourceFileMap[filename];
+  } else {
+    Constant * FInit = ConstantArray::get (CI->getContext(), filename);
+    Module * M = CI->getParent()->getParent()->getParent();
+    SourceFile = new GlobalVariable (*M,
+                                     FInit->getType(),
+                                     true,
+                                     GlobalValue::InternalLinkage,
+                                     FInit,
+                                     "sourcefile");
+    SourceFileMap[filename] = SourceFile;
+  }
+
+  return std::make_pair (SourceFile, LineNumber);
+}
+
+//
+// Method: operator()
+//
+// Description:
+//  Return the source information associated with a value within the call
+//  instruction.  This is mainly intended to provide better source file
+//  information to poolregister() calls.
+//
+// Inputs:
+//  CI - The call instruction
+//
+// Return value:
+//  A pair of LLVM values.  The first is the source file name; the second is
+//  the line number.  Default values are given if no source line information
+//  can be found.
+//
+std::pair<Value *, Value *>
+VariableSourceInfo::operator() (CallInst * CI) {
+  assert (((CI->getNumOperands()) > 2) &&
+          "Not enough information to get debug info!\n");
+
+  Value * LineNumber;
+  Value * SourceFile;
+
+  //
+  // Create a default line number and source file information for the call.
+  //
+  LineNumber = ConstantInt::get (Int32Type, 0);
+  std::string filename = "<unknown>";
+  Module * M = CI->getParent()->getParent()->getParent();
+
+  //
+  // Get the value for which we want debug information.
+  //
+  Value * V = CI->getOperand(2)->stripPointerCasts();
+  
+  //
+  // Try to get information about where in the program the value was allocated.
+  //
+  if (GlobalVariable * GV = dyn_cast<GlobalVariable>(V)) {
+    NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv");
+    if (NMD) {
+      for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+        DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i)));
+        if (!DIG.isGlobalVariable())
+          continue;
+        if (DIGlobalVariable(NMD->getOperand(i)).getGlobal() == GV) {
+          DIGlobalVariable Var(NMD->getOperand(i));
+          LineNumber = ConstantInt::get (Int32Type, Var.getLineNumber());
+          filename = Var.getCompileUnit().getDirectory().str() + Var.getCompileUnit().getFilename().str();
+        }
+      }
+    }
+  } else {
+    if (Instruction *I = dyn_cast<Instruction>(V))
+      if (MDNode *Dbg = I->getMetadata(dbgKind)) {
+        DILocation Loc (Dbg);
+        filename = Loc.getDirectory().str() + Loc.getFilename().str();
+        LineNumber = ConstantInt::get (Int32Type, Loc.getLineNumber());
+      }
+  }
+  if (SourceFileMap.find (filename) != SourceFileMap.end()) {
+    SourceFile = SourceFileMap[filename];
+  } else {
+    Constant * FInit = ConstantArray::get (CI->getContext(), filename);
+    Module * M = CI->getParent()->getParent()->getParent();
+    SourceFile = new GlobalVariable (*M,
+                                     FInit->getType(),
+                                     true,
+                                     GlobalValue::InternalLinkage,
+                                     FInit,
+                                     "sourcefile");
+    SourceFileMap[filename] = SourceFile;
+  }
+  return std::make_pair (SourceFile, LineNumber);
+}
+
+
+//
+// Method: processFunction()
+//
+// Description:
+//  Process each function in the module.
+//
+// Inputs:
+//  F - The function to transform into a debug version.  This *can be NULL.
+//
+void
+DebugInstrument::transformFunction (Function * F, GetSourceInfo & SI) {
+  // If the function does not exist within the module, it does not need to
+  // be transformed.
+  if (!F) return;
+
+  //
+  // Create the function prototype for the debug version of the function.  This
+  // function will have an identical type to the original *except* that it will
+  // have additional debug parameters at the end.
+  //
+  const FunctionType * FuncType = F->getFunctionType();
+  std::vector<Type *> ParamTypes (FuncType->param_begin(),
+                                  FuncType->param_end());
+  ParamTypes.push_back (Int32Type);
+  ParamTypes.push_back (VoidPtrTy);
+  ParamTypes.push_back (Int32Type);
+
+  //
+  // Check to see if the debug version of the function already exists.
+  //
+  bool hadToCreateFunction = true;
+  if (F->getParent()->getFunction(F->getName().str() + "_debug"))
+    hadToCreateFunction = false;
+
+  FunctionType * DebugFuncType = FunctionType::get (FuncType->getReturnType(),
+                                                    ParamTypes,
+                                                    false);
+  std::string funcdebugname = F->getName().str() + "_debug";
+  Constant * FDebug = F->getParent()->getOrInsertFunction (funcdebugname,
+                                                           DebugFuncType);
+
+  //
+  // Give the function a body.  This is used for ensuring that SAFECode plays
+  // nicely with LLVM's bugpoint tool.  By having a body, the program will link
+  // correctly even when the intrinsic renaming pass is removed by bugpoint.
+  //
+  if (hadToCreateFunction) {
+    Function * DebugFunc = dyn_cast<Function>(FDebug);
+    assert (DebugFunc);
+
+    LLVMContext & Context = F->getContext();
+    BasicBlock * entryBB=BasicBlock::Create (Context, "entry", DebugFunc);
+    Type * VoidTy = Type::getVoidTy(Context);
+    if (DebugFunc->getReturnType() == VoidTy) {
+      ReturnInst::Create (Context, entryBB);
+    } else {
+      Value * retValue = UndefValue::get (DebugFunc->getReturnType());
+      ReturnInst::Create (Context, retValue, entryBB);
+    }
+  }
+
+  //
+  // Create a set of call instructions that must be modified.
+  //
+  std::vector<CallInst *> Worklist;
+  Function::use_iterator i, e;
+  for (i = F->use_begin(), e = F->use_end(); i != e; ++i) {
+    if (CallInst * CI = dyn_cast<CallInst>(*i)) {
+      Worklist.push_back (CI);
+    }
+  }
+
+  //
+  // Process all call instructions in the worklist.
+  //
+  while (Worklist.size()) {
+    CallInst * CI = Worklist.back();
+    Worklist.pop_back();
+
+    //
+    // Get the line number and source file information for the call.
+    //
+    Value * LineNumber;
+    Value * SourceFile;
+    std::pair<Value *, Value *> Info = SI (CI);
+    SourceFile = Info.first;
+    LineNumber = Info.second;
+
+    //
+    // If the source filename is in the meta-data section, make a copy of it in
+    // the default section.  This ensures that it gets code generated.
+    //
+    if (ConstantExpr * GEP = dyn_cast<ConstantExpr>(SourceFile)) {
+      if (GlobalVariable * GV = dyn_cast<GlobalVariable>(GEP->getOperand(0))) {
+        if (GV->hasSection()) {
+          GlobalVariable * SrcGV = new GlobalVariable (*(F->getParent()),
+                                                       GV->getType()->getElementType(),
+                                                       GV->isConstant(),
+                                                       GV->getLinkage(),
+                                                       GV->getInitializer(),
+                                                       GV->getName(),
+                                                       0,
+                                                       GV->isThreadLocal(),
+                                                       0);
+          SrcGV->copyAttributesFrom (GV);
+          SrcGV->setSection ("");
+          SourceFile = SrcGV;
+        }
+      }
+    }
+
+    //
+    // Transform the function call.
+    //
+    std::vector<Value *> args (CI->op_begin(), CI->op_end());
+    args.erase (args.begin());
+    args.push_back (ConstantInt::get(Int32Type, tagCounter++));
+
+    args.push_back (castTo (SourceFile, VoidPtrTy, "", CI));
+    args.push_back (LineNumber);
+
+    CallInst * NewCall = CallInst::Create (FDebug,
+                                           args,
+                                           CI->getName(),
+                                           CI);
+    CI->replaceAllUsesWith (NewCall);
+    CI->eraseFromParent();
+  }
+
+  return;
+}
+
+//
+// Method: runOnModule()
+//
+// Description:
+//  This is where the pass begin execution.
+//
+// Return value:
+//  true  - The module was modified.
+//  false - The module was left unmodified.
+//
+bool
+DebugInstrument::runOnModule (Module &M) {
+  // Create the void pointer type
+  VoidPtrTy = getVoidPtrType(M);
+
+  //
+  // Create needed LLVM types.
+  //
+  VoidType  = Type::getVoidTy(M.getContext());
+  Int8Type  = IntegerType::getInt8Ty(M.getContext());
+  Int32Type = IntegerType::getInt32Ty(M.getContext());
+
+  //
+  // Get the ID number for debug metadata.
+  //
+  unsigned dbgKind = M.getContext().getMDKindID("dbg");
+
+  //
+  // Transform allocations, load/store checks, and bounds checks.
+  //
+  LocationSourceInfo LInfo (dbgKind);
+  VariableSourceInfo VInfo (dbgKind);
+
+  // FIXME: Technically it should user intrinsic everywhere..
+  transformFunction (M.getFunction ("poolalloc"), LInfo);
+  transformFunction (M.getFunction ("poolcalloc"), LInfo);
+  transformFunction (M.getFunction ("poolrealloc"), LInfo);
+  transformFunction (M.getFunction ("poolstrdup"), LInfo);
+  transformFunction (M.getFunction ("poolfree"), LInfo);
+  transformFunction (M.getFunction ("sc.lscheck"), VInfo);
+  transformFunction (M.getFunction ("sc.lscheckui"), VInfo);
+  transformFunction (M.getFunction ("sc.lscheckalign"), VInfo);
+  transformFunction (M.getFunction ("sc.lscheckalignui"), VInfo);
+  transformFunction (M.getFunction ("sc.boundscheck"), VInfo);
+  transformFunction (M.getFunction ("sc.boundscheckui"), VInfo);
+  transformFunction (M.getFunction ("sc.exactcheck2"), VInfo);
+  transformFunction (M.getFunction ("sc.pool_register"), VInfo);
+  transformFunction (M.getFunction ("sc.pool_register_stack"), VInfo);
+  transformFunction (M.getFunction ("sc.pool_unregister"), VInfo);
+  transformFunction (M.getFunction ("sc.pool_unregister_stack"), VInfo);
+
+  // CStdLib
+  transformFunction(M.getFunction("pool_strcpy"),  LInfo);
+  transformFunction(M.getFunction("pool_strncpy"), LInfo);
+  transformFunction(M.getFunction("pool_strlen"),  LInfo);
+  transformFunction(M.getFunction("pool_strchr"),  LInfo);
+  transformFunction(M.getFunction("pool_strrchr"), LInfo);
+  transformFunction(M.getFunction("pool_strncat"), LInfo);
+  transformFunction(M.getFunction("pool_strcat"),  LInfo);
+  transformFunction(M.getFunction("pool_strstr"),  LInfo);
+  transformFunction(M.getFunction("pool_strpbrk"), LInfo);
+
+  transformFunction(M.getFunction("pool_strcmp"),  LInfo);
+  transformFunction(M.getFunction("pool_strncmp"), LInfo);
+  transformFunction(M.getFunction("pool_memcmp"),  LInfo);
+  transformFunction(M.getFunction("pool_strspn"),  LInfo);
+  transformFunction(M.getFunction("pool_strcspn"), LInfo);
+  transformFunction(M.getFunction("pool_memccpy"), LInfo);
+  transformFunction(M.getFunction("pool_memchr"),  LInfo);
+  transformFunction(M.getFunction("pool_stpcpy"),  LInfo);
+  transformFunction(M.getFunction("pool_bcmp"),    LInfo);
+  transformFunction(M.getFunction("pool_bcopy"),   LInfo);
+  transformFunction(M.getFunction("pool_index"),   LInfo);
+  transformFunction(M.getFunction("pool_rindex"),  LInfo);
+  transformFunction(M.getFunction("pool_strcasestr"),  LInfo);
+  transformFunction(M.getFunction("pool_strcasecmp"),  LInfo);
+  transformFunction(M.getFunction("pool_strncasecmp"), LInfo);
+
+#if 0
+  transformFunction(M.getFunction("pool_memcpy"),  LInfo);
+  transformFunction(M.getFunction("pool_mempcpy"), LInfo);
+  transformFunction(M.getFunction("pool_memmove"), LInfo);
+  transformFunction(M.getFunction("pool_memset"),  LInfo);
+#endif
+
+  return true;
+}
+
+}
+
Index: lib/Transforms/MemSafety/RegisterRuntimeInitializer.cpp
===================================================================
--- lib/Transforms/MemSafety/RegisterRuntimeInitializer.cpp	(revision 0)
+++ lib/Transforms/MemSafety/RegisterRuntimeInitializer.cpp	(revision 0)
@@ -0,0 +1,173 @@
+//===- RegisterRuntimeInitializer.cpp ---------------------------*- C++ -*----//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// Pass to register runtime initialization calls into user-space programs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Constants.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Transforms/MemSafety/RegisterRuntimeInitializer.h"
+#include "llvm/Transforms/MemSafety/Utility.h"
+
+using namespace llvm;
+
+namespace llvm {
+
+char RegisterRuntimeInitializer::ID = 0;
+
+static llvm::RegisterPass<RegisterRuntimeInitializer>
+X1 ("reg-runtime-init", "Register runtime initializer into programs");
+
+bool
+RegisterRuntimeInitializer::runOnModule(llvm::Module & M) {
+  constructInitializer(M);
+  insertInitializerIntoGlobalCtorList(M);
+  return true;
+}
+
+void
+RegisterRuntimeInitializer::constructInitializer(llvm::Module & M) {
+  //
+  // Create a new function with zero arguments.  This will be the SAFECode
+  // run-time constructor; it will be called by static global variable
+  // constructor magic before main() is called.
+  //
+  Type * VoidTy  = Type::getVoidTy (M.getContext());
+  Type * Int32Ty = IntegerType::getInt32Ty(M.getContext());
+  Function * RuntimeCtor = (Function *) M.getOrInsertFunction("pool_ctor",
+                                                              VoidTy,
+                                                              NULL);
+
+  Function * RuntimeInit = (Function *) M.getOrInsertFunction("pool_init_runtime", VoidTy, Int32Ty, Int32Ty, Int32Ty, NULL);
+  Constant * CF = M.getOrInsertFunction ("sc.register_globals", VoidTy, NULL);
+  Function * RegGlobals  = dyn_cast<Function>(CF);
+
+  //
+  // Make the global registration function internal.
+  //
+  RegGlobals->setDoesNotThrow();
+  RegGlobals->setLinkage(GlobalValue::InternalLinkage);
+
+  // Make the runtime constructor compatible with other ctors
+  RuntimeCtor->setDoesNotThrow();
+  RuntimeCtor->setLinkage(GlobalValue::InternalLinkage);
+
+  //
+  // Empty out the default definition of the SAFECode constructor function.
+  // We'll replace it with our own code.
+  //
+  destroyFunction (RuntimeCtor);
+
+  //
+  // Add a call in the new constructor function to the SAFECode initialization
+  // function.
+  //
+  BasicBlock * BB = BasicBlock::Create (M.getContext(), "entry", RuntimeCtor);
+ 
+  // Delegate the responbilities of initializing pool descriptor to the 
+  // SAFECode runtime initializer
+//  CallInst::Create (PoolInit, "", BB); 
+
+  Type * Int32Type = IntegerType::getInt32Ty(M.getContext());
+  std::vector<Value *> args;
+
+  //
+  // FIXME: For now, assume explicit dangling pointer checks are disabled,
+  //        rewrite pointers are enabled, and that we should terminate on
+  //        errors.  Some more refactoring will be needed to make all of this
+  //        work properly.
+  //
+#if 0
+  if (SCConfig.dpChecks())
+    args.push_back (ConstantInt::get(Int32Type, 1));
+  else
+    args.push_back (ConstantInt::get(Int32Type, 0));
+  args.push_back (ConstantInt::get(Int32Type, SCConfig.rewriteOOB()));
+  args.push_back (ConstantInt::get(Int32Type, SCConfig.terminateOnErrors()));
+#else
+  args.push_back (ConstantInt::get(Int32Type, 0));
+  args.push_back (ConstantInt::get(Int32Type, 1));
+  args.push_back (ConstantInt::get(Int32Type, 1));
+#endif
+  CallInst::Create (RuntimeInit, args, "", BB); 
+
+  args.clear();
+  CallInst::Create (RegGlobals, args, "", BB);
+
+
+  //
+  // Add a return instruction at the end of the basic block.
+  //
+  ReturnInst::Create (M.getContext(), BB);
+}
+
+void
+RegisterRuntimeInitializer::insertInitializerIntoGlobalCtorList(Module & M) {
+  Function * RuntimeCtor = M.getFunction ("pool_ctor");
+
+  //
+  // Insert the run-time ctor into the ctor list.
+  //
+  Type * Int32Type = IntegerType::getInt32Ty(M.getContext());
+  std::vector<Constant *> CtorInits;
+  CtorInits.push_back (ConstantInt::get (Int32Type, 0));
+  CtorInits.push_back (RuntimeCtor);
+  StructType * ST = ConstantStruct::getTypeForElements (CtorInits, false);
+  Constant * RuntimeCtorInit = ConstantStruct::get (ST, CtorInits);
+
+  //
+  // Get the current set of static global constructors and add the new ctor
+  // to the list.
+  //
+  std::vector<Constant *> CurrentCtors;
+  GlobalVariable * GVCtor = M.getNamedGlobal ("llvm.global_ctors");
+  if (GVCtor) {
+    if (Constant * C = GVCtor->getInitializer()) {
+      for (unsigned index = 0; index < C->getNumOperands(); ++index) {
+        CurrentCtors.push_back (dyn_cast<Constant>(C->getOperand (index)));
+      }
+    }
+  }
+
+  //
+  // The ctor list seems to be initialized in different orders on different
+  // platforms, and the priority settings don't seem to work.  Examine the
+  // module's platform string and take a best guess to the order.
+  //
+  if (M.getTargetTriple().find ("linux") == std::string::npos)
+    CurrentCtors.insert (CurrentCtors.begin(), RuntimeCtorInit);
+  else
+    CurrentCtors.push_back (RuntimeCtorInit);
+
+  assert (CurrentCtors.back()->getType() == RuntimeCtorInit->getType());
+
+  //
+  // Create a new initializer.
+  //
+  ArrayType * AT = ArrayType::get (RuntimeCtorInit-> getType(),
+                                   CurrentCtors.size());
+  Constant * NewInit=ConstantArray::get (AT, CurrentCtors);
+
+  //
+  // Create the new llvm.global_ctors global variable and replace all uses of
+  // the old global variable with the new one.
+  //
+  Value * newGVCtor = new GlobalVariable (M,
+                                          NewInit->getType(),
+                                          false,
+                                          GlobalValue::AppendingLinkage,
+                                          NewInit,
+                                          "llvm.global_ctors");
+  if (GVCtor)
+    newGVCtor->takeName (GVCtor);
+  return;
+}
+
+}
Index: lib/Transforms/MemSafety/Makefile
===================================================================
--- lib/Transforms/MemSafety/Makefile	(revision 0)
+++ lib/Transforms/MemSafety/Makefile	(revision 0)
@@ -0,0 +1,15 @@
+##===- lib/Transforms/MemSafety/Makefile -------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+LIBRARYNAME = LLVMsc
+BUILD_ARCHIVE = 1
+
+include $(LEVEL)/Makefile.common
+
Index: lib/Transforms/MemSafety/RegisterStackObjPass.cpp
===================================================================
--- lib/Transforms/MemSafety/RegisterStackObjPass.cpp	(revision 0)
+++ lib/Transforms/MemSafety/RegisterStackObjPass.cpp	(revision 0)
@@ -0,0 +1,443 @@
+//===- RegisterStackObjPass.cpp - Pass to Insert Stack Object Registration ---//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This pass instruments code to register stack objects with the appropriate
+// pool.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "stackreg"
+
+#include "llvm/ADT/VectorExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Instruction.h"
+#include "llvm/Module.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Transforms/MemSafety/Utility.h"
+#include "llvm/Transforms/MemSafety/RegisterBounds.h"
+#include "llvm/Transforms/Utils/PromoteMemToReg.h"
+
+namespace llvm {
+
+char RegisterStackObjPass::ID = 0;
+
+static RegisterPass<RegisterStackObjPass> passRegStackObj ("reg-stack-obj", "register stack objects into pools");
+
+// Pass Statistics
+namespace {
+  // Object registration statistics
+  STATISTIC (StackRegisters,      "Stack registrations");
+  STATISTIC (SavedRegAllocs,      "Stack registrations avoided");
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Static Functions
+////////////////////////////////////////////////////////////////////////////
+
+// Prototypes of the poolunregister function
+static Constant * StackFree = 0;
+
+//
+// Function: insertPoolFrees()
+//
+// Description:
+//  This function takes a list of alloca instructions and inserts code to
+//  unregister them at every unwind and return instruction.
+//
+// Inputs:
+//  PoolRegisters - The list of calls to poolregister() inserted for stack
+//                  objects.
+//  ExitPoints    - The list of instructions that can cause the function to
+//                  return.
+//  Context       - The LLVM Context in which to insert instructions.
+//
+void
+RegisterStackObjPass::insertPoolFrees
+  (const std::vector<CallInst *> & PoolRegisters,
+   const std::vector<Instruction *> & ExitPoints,
+   LLVMContext * Context) {
+  // List of alloca instructions we create to store the pointers to be
+  // deregistered.
+  std::vector<AllocaInst *> PtrList;
+
+  // List of pool handles; this is a parallel array to PtrList
+  std::vector<Value *> PHList;
+
+  // The infamous void pointer type
+  PointerType * VoidPtrTy = getVoidPtrType(*Context);
+
+  //
+  // Create alloca instructions for every registered alloca.  These will hold
+  // a pointer to the registered stack objects and will be referenced by
+  // poolunregister().
+  //
+  for (unsigned index = 0; index < PoolRegisters.size(); ++index) {
+    //
+    // Take the first element off of the worklist.
+    //
+    CallInst * CI = PoolRegisters[index];
+    CallSite CS(CI);
+
+    //
+    // Get the pool handle and allocated pointer from the poolregister() call.
+    //
+    Value * PH  = CS.getArgument(0);
+    Value * Ptr = CS.getArgument(1);
+
+    //
+    // Create a place to store the pointer returned from alloca.  Initialize it
+    // with a null pointer.
+    //
+    BasicBlock & EntryBB = CI->getParent()->getParent()->getEntryBlock();
+    Instruction * InsertPt = &(EntryBB.front());
+    AllocaInst * PtrLoc = new AllocaInst (VoidPtrTy,
+                                          Ptr->getName() + ".st",
+                                          InsertPt);
+    Value * NullPointer = ConstantPointerNull::get(VoidPtrTy);
+    new StoreInst (NullPointer, PtrLoc, InsertPt);
+
+    //
+    // Store the registered pointer into the memory we allocated in the entry
+    // block.
+    //
+    new StoreInst (Ptr, PtrLoc, CI);
+
+    //
+    // Record the alloca that stores the pointer to deregister.
+    // Record the pool handle with it.
+    //
+    PtrList.push_back (PtrLoc);
+    PHList.push_back (PH);
+  }
+
+  //
+  // For each point where the function can exit, insert code to deregister all
+  // stack objects.
+  //
+  for (unsigned index = 0; index < ExitPoints.size(); ++index) {
+    //
+    // Take the first element off of the worklist.
+    //
+    Instruction * Return = ExitPoints[index];
+
+    //
+    // Deregister each registered stack object.
+    //
+    for (unsigned i = 0; i < PtrList.size(); ++i) {
+      //
+      // Get the location holding the pointer and the pool handle associated
+      // with it.
+      //
+      AllocaInst * PtrLoc = PtrList[i];
+      Value * PH = PHList[i];
+
+      //
+      // Generate a load instruction to get the registered pointer.
+      //
+      LoadInst * Ptr = new LoadInst (PtrLoc, "", Return);
+
+      //
+      // Create the call to poolunregister().
+      //
+      std::vector<Value *> args;
+      args.push_back (PH);
+      args.push_back (Ptr);
+      CallInst::Create (StackFree, args, "", Return);
+    }
+  }
+
+  //
+  // Lastly, promote the allocas we created into LLVM virtual registers.
+  //
+  PromoteMemToReg(PtrList, *DT);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// RegisterStackObjPass Methods
+////////////////////////////////////////////////////////////////////////////
+ 
+//
+// Method: runOnFunction()
+//
+// Description:
+//  This is the entry point for this LLVM function pass.  The pass manager will
+//  call this method for every function in the Module that will be transformed.
+//
+// Inputs:
+//  F - A reference to the function to transform.
+//
+// Outputs:
+//  F - The function will be modified to register and unregister stack objects.
+//
+// Return value:
+//  true  - The function was modified.
+//  false - The function was not modified.
+//
+bool
+RegisterStackObjPass::runOnFunction(Function & F) {
+  //
+  // Get prerequisite analysis information.
+  //
+  TD = &getAnalysis<TargetData>();
+  LI = &getAnalysis<LoopInfo>();
+  DT = &getAnalysis<DominatorTree>();
+  DF = &getAnalysis<DominanceFrontier>();
+
+  //
+  // Get pointers to the functions for registering and unregistering pointers.
+  //
+  PoolRegister = F.getParent()->getFunction ("pool_register_stack");
+  StackFree    = F.getParent()->getFunction ("pool_unregister_stack");
+  assert (PoolRegister);
+  assert (StackFree);
+
+  // The set of registered stack objects
+  std::vector<CallInst *> PoolRegisters;
+
+  // The set of stack objects within the function.
+  std::vector<AllocaInst *> AllocaList;
+
+  // The set of instructions that can cause the function to return to its
+  // caller.
+  std::vector<Instruction *> ExitPoints;
+
+  //
+  // Scan the function to register allocas and find locations where registered
+  // allocas to be deregistered.
+  //
+  for (Function::iterator BI = F.begin(); BI != F.end(); ++BI) {
+    //
+    // Create a list of alloca instructions to register.  Note that we create
+    // the list ahead of time because registerAllocaInst() will create new
+    // alloca instructions.
+    //
+    for (BasicBlock::iterator I = BI->begin(); I != BI->end(); ++I) {
+      if (AllocaInst * AI = dyn_cast<AllocaInst>(I)) {
+        //
+        // Ensure that the alloca is not within a loop; we don't support yet.
+        //
+#if 0
+        if (LI->getLoopFor (BI)) {
+          assert (0 &&
+                  "Register Stack Objects: No support for alloca in loop!\n");
+          abort();
+        }
+        AllocaList.push_back (AI);
+#else
+        if (!(LI->getLoopFor (BI))) {
+          AllocaList.push_back (AI);
+        }
+#endif
+      }
+    }
+
+    //
+    // Add calls to register the allocated stack objects.
+    //
+    while (AllocaList.size()) {
+      AllocaInst * AI = AllocaList.back();
+      AllocaList.pop_back();
+      if (CallInst * CI = registerAllocaInst (AI))
+        PoolRegisters.push_back(CI);
+    }
+
+    //
+    // If the terminator instruction of this basic block can return control
+    // flow back to the caller, mark it as a place where a deregistration
+    // is needed.
+    //
+    Instruction * Terminator = BI->getTerminator();
+    if ((isa<ReturnInst>(Terminator)) || (isa<UnwindInst>(Terminator))) {
+      ExitPoints.push_back (Terminator);
+    }
+  }
+
+  //
+  // Insert poolunregister calls for all of the registered allocas.
+  //
+  insertPoolFrees (PoolRegisters, ExitPoints, &F.getContext());
+
+  //
+  // Conservatively assume that we've changed the function.
+  //
+  return true;
+}
+
+//
+// Method: registerAllocaInst()
+//
+// Description:
+//  Register a single alloca instruction.
+//
+// Inputs:
+//  AI - The alloca which requires registration.
+//
+// Return value:
+//  NULL - The alloca was not registered.
+//  Otherwise, the call to poolregister() is returned.
+//
+CallInst *
+RegisterStackObjPass::registerAllocaInst (AllocaInst *AI) {
+  //
+  // Determine if any use (direct or indirect) escapes this function.  If
+  // not, then none of the checks will consult the MetaPool, and we can
+  // forego registering the alloca.
+  //
+#if 0
+  bool MustRegisterAlloca = false;
+#else
+  //
+  // FIXME: For now, register all allocas.  The reason is that this
+  // optimization requires that other optimizations be executed, and those are
+  // not integrated into LLVM yet.
+  //
+  bool MustRegisterAlloca = true;
+#endif
+  std::vector<Value *> AllocaWorkList;
+  AllocaWorkList.push_back (AI);
+  while ((!MustRegisterAlloca) && (AllocaWorkList.size())) {
+    Value * V = AllocaWorkList.back();
+    AllocaWorkList.pop_back();
+    Value::use_iterator UI = V->use_begin();
+    for (; UI != V->use_end(); ++UI) {
+      // We cannot handle PHI nodes or Select instructions
+      if (isa<PHINode>(*UI) || isa<SelectInst>(*UI)) {
+        MustRegisterAlloca = true;
+        continue;
+      }
+
+      // The pointer escapes if it's stored to memory somewhere.
+      StoreInst * SI;
+      if ((SI = dyn_cast<StoreInst>(*UI)) && (SI->getOperand(0) == V)) {
+        MustRegisterAlloca = true;
+        continue;
+      }
+
+      // GEP instructions are okay, but need to be added to the worklist
+      if (isa<GetElementPtrInst>(*UI)) {
+        AllocaWorkList.push_back (*UI);
+        continue;
+      }
+
+      // Cast instructions are okay as long as they cast to another pointer
+      // type
+      if (CastInst * CI = dyn_cast<CastInst>(*UI)) {
+        if (isa<PointerType>(CI->getType())) {
+          AllocaWorkList.push_back (*UI);
+          continue;
+        } else {
+          MustRegisterAlloca = true;
+          continue;
+        }
+      }
+
+#if 0
+      if (ConstantExpr *cExpr = dyn_cast<ConstantExpr>(*UI)) {
+        if (cExpr->getOpcode() == Instruction::Cast) {
+          AllocaWorkList.push_back (*UI);
+          continue;
+        } else {
+          MustRegisterAlloca = true;
+          continue;
+        }
+      }
+#endif
+
+      CallInst * CI1;
+      if ((CI1 = dyn_cast<CallInst>(*UI))) {
+        if (!(CI1->getCalledFunction())) {
+          MustRegisterAlloca = true;
+          continue;
+        }
+
+        std::string FuncName = CI1->getCalledFunction()->getName();
+        if (FuncName == "exactcheck3") {
+          AllocaWorkList.push_back (*UI);
+          continue;
+        } else if ((FuncName == "llvm.memcpy.i32")    || 
+                   (FuncName == "llvm.memcpy.i64")    ||
+                   (FuncName == "llvm.memset.i32")    ||
+                   (FuncName == "llvm.memset.i64")    ||
+                   (FuncName == "llvm.memmove.i32")   ||
+                   (FuncName == "llvm.memmove.i64")   ||
+                   (FuncName == "llva_memcpy")        ||
+                   (FuncName == "llva_memset")        ||
+                   (FuncName == "llva_strncpy")       ||
+                   (FuncName == "llva_invokememcpy")  ||
+                   (FuncName == "llva_invokestrncpy") ||
+                   (FuncName == "llva_invokememset")  ||
+                   (FuncName == "memcmp")) {
+          continue;
+        } else {
+          MustRegisterAlloca = true;
+          continue;
+        }
+      }
+    }
+  }
+
+  if (!MustRegisterAlloca) {
+    ++SavedRegAllocs;
+    return 0;
+  }
+
+  //
+  // Insert the alloca registration.
+  //
+
+  //
+  // Create an LLVM Value for the allocation size.  Insert a multiplication
+  // instruction if the allocation allocates an array.
+  //
+  Type * Int32Type = IntegerType::getInt32Ty(AI->getContext());
+  unsigned allocsize = TD->getTypeAllocSize(AI->getAllocatedType());
+  Value *AllocSize = ConstantInt::get (AI->getOperand(0)->getType(), allocsize);
+  if (AI->isArrayAllocation()) {
+    Value * Operand = AI->getOperand(0);
+    AllocSize = BinaryOperator::Create(Instruction::Mul,
+                                       AllocSize,
+                                       Operand,
+                                       "sizetmp",
+                                       AI);
+  }
+  AllocSize = castTo (AllocSize, Int32Type, "sizetmp", AI);
+
+  //
+  // Attempt to insert the call to register the alloca'ed object after all of
+  // the alloca instructions in the basic block.
+  //
+  Instruction *iptI = AI;
+  BasicBlock::iterator InsertPt = AI;
+  iptI = ++InsertPt;
+  if (AI->getParent() == (&(AI->getParent()->getParent()->getEntryBlock()))) {
+    InsertPt = AI->getParent()->begin();
+    while (&(*(InsertPt)) != AI)
+      ++InsertPt;
+    while (isa<AllocaInst>(InsertPt))
+      ++InsertPt;
+    iptI = InsertPt;
+  }
+
+  //
+  // Insert a call to register the object.
+  //
+  PointerType * VoidPtrTy = getVoidPtrType(AI->getContext());
+  Instruction *Casted = castTo (AI, VoidPtrTy, AI->getName()+".casted", iptI);
+  Value * CastedPH    = ConstantPointerNull::get (VoidPtrTy);
+  std::vector<Value *> args;
+  args.push_back (CastedPH);
+  args.push_back (Casted);
+  args.push_back (AllocSize);
+
+  // Update statistics
+  ++StackRegisters;
+  return CallInst::Create (PoolRegister, args, "", iptI);
+}
+
+}
Index: lib/Transforms/MemSafety/AllocatorInfo.cpp
===================================================================
--- lib/Transforms/MemSafety/AllocatorInfo.cpp	(revision 0)
+++ lib/Transforms/MemSafety/AllocatorInfo.cpp	(revision 0)
@@ -0,0 +1,203 @@
+//===- AllocatorInfo.cpp ----------------------------------------*- C++ -*----//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// Define the abstraction of a pair of allocator / deallocator, including:
+//
+//   * The size of the object being allocated. 
+//   * Whether the size may be a constant, which can be used for exactcheck
+// optimization.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Constants.h"
+#include "llvm/Instructions.h"
+#include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Transforms/MemSafety/AllocatorInfo.h"
+
+using namespace llvm;
+
+namespace llvm {
+
+AllocatorInfo::~AllocatorInfo() {}
+
+char AllocatorInfoPass::ID = 0;
+
+static RegisterPass<AllocatorInfoPass>
+X ("allocinfo", "Allocator Information Pass");
+
+Value *
+SimpleAllocatorInfo::getAllocSize(Value * AllocSite) const {
+  CallInst * CI = dyn_cast<CallInst>(AllocSite);
+  if (!CI)
+    return NULL;
+
+  Function * F  = dyn_cast<Function>(CI->getCalledValue()->stripPointerCasts());
+  if (!F || F->getName() != allocCallName) 
+    return NULL;
+
+  CallSite CS(CI);
+  return CS.getArgument(allocSizeOperand - 1);
+}
+
+Value *
+SimpleAllocatorInfo::getOrCreateAllocSize(Value * AllocSite) const {
+  return getAllocSize (AllocSite);
+}
+
+Value *
+ArrayAllocatorInfo::getOrCreateAllocSize(Value * AllocSite) const {
+  //
+  // See if this is a call to the allocator.  If not, return NULL.
+  //
+  CallInst * CI = dyn_cast<CallInst>(AllocSite);
+  if (!CI)
+    return NULL;
+
+  Function * F  = dyn_cast<Function>(CI->getCalledValue()->stripPointerCasts());
+  if (!F || F->getName() != allocCallName) 
+    return NULL;
+
+  //
+  // Insert a multiplication instruction to compute the size of the array
+  // allocation.
+  //
+  CallSite CS(CI);
+  return BinaryOperator::Create (BinaryOperator::Mul,
+                                 CS.getArgument(allocSizeOperand - 1),
+                                 CS.getArgument(allocNumOperand - 1),
+                                 "size",
+                                 CI);
+}
+
+Value *
+StringAllocatorInfo::getOrCreateAllocSize (Value * AllocSite) const {
+  //
+  // See if this is a call to the allocator.  If not, return NULL.
+  //
+  CallInst * CI = dyn_cast<CallInst>(AllocSite);
+  if (!CI)
+    return NULL;
+
+  Function * F  = dyn_cast<Function>(CI->getCalledValue()->stripPointerCasts());
+  if (!F || F->getName() != allocCallName) 
+    return NULL;
+
+  //
+  // Insert a call to strlen() to determine the length of the string that was
+  // allocated.
+  //
+  Module * M = CI->getParent()->getParent()->getParent();
+  Function * Strlen = M->getFunction ("strlen");
+  assert (Strlen && "No strlen function in the module");
+  CallSite CS(CI);
+  BasicBlock::iterator InsertPt = CI;
+  ++InsertPt;
+  return CallInst::Create (Strlen, CS.getArgument(0), "", InsertPt);
+}
+
+Value *
+SimpleAllocatorInfo::getFreedPointer(Value * FreeSite) const {
+  CallInst * CI = dyn_cast<CallInst>(FreeSite);
+
+  Function * F  = dyn_cast<Function>(CI->getCalledValue()->stripPointerCasts());
+  if (!F || F->getName() != freeCallName) 
+    return NULL;
+
+  CallSite CS(CI);
+  return CS.getArgument(freePtrOperand-1);
+}
+
+Value *
+ReAllocatorInfo::getAllocedPointer (Value * AllocSite) const {
+  CallInst * CI = dyn_cast<CallInst>(AllocSite);
+
+  Function * F  = dyn_cast<Function>(CI->getCalledValue()->stripPointerCasts());
+  if (!F || F->getName() != allocCallName) 
+    return NULL;
+
+  CallSite CS(CI);
+  return CS.getArgument(allocPtrOperand-1);
+}
+
+//
+// Method: getObjectSize()
+//
+// Description:
+//  Try to get an LLVM value that represents the size of the memory object
+//  referenced by the specified pointer.
+//
+Value *
+AllocatorInfoPass::getObjectSize(Value * V) {
+  // Get access to the target data information
+  TargetData & TD = getAnalysis<TargetData>();
+
+  //
+  // Finding the size of a global variable is easy.
+  //
+  Type * Int32Type = IntegerType::getInt32Ty(V->getContext());
+  if (GlobalVariable * GV = dyn_cast<GlobalVariable>(V)) {
+    Type * allocType = GV->getType()->getElementType();
+    return ConstantInt::get (Int32Type, TD.getTypeAllocSize (allocType));
+  }
+
+  //
+  // Find the size of byval function arguments is also easy.
+  //
+  if (Argument * AI = dyn_cast<Argument>(V)) {
+    if (AI->hasByValAttr()) {
+      assert (isa<PointerType>(AI->getType()));
+      PointerType * PT = cast<PointerType>(AI->getType());
+      unsigned int type_size = TD.getTypeAllocSize (PT->getElementType());
+      return ConstantInt::get (Int32Type, type_size);
+    }
+  }
+
+  //
+  // Alloca instructions are a little harder but not bad.
+  //
+  if (AllocaInst * AI = dyn_cast<AllocaInst>(V)) {
+    unsigned int type_size = TD.getTypeAllocSize (AI->getAllocatedType());
+    if (AI->isArrayAllocation()) {
+      if (ConstantInt * CI = dyn_cast<ConstantInt>(AI->getArraySize())) {
+        if (CI->getSExtValue() > 0) {
+          type_size *= CI->getSExtValue();
+        } else {
+          return NULL;
+        }
+      } else {
+        return NULL;
+      }
+    }
+    return ConstantInt::get(Int32Type, type_size);
+  }
+
+  //
+  // Heap (i.e., customized) allocators are the most difficult, but we can
+  // manage.
+  //
+  if (CallInst * CI = dyn_cast<CallInst>(V)) {
+    Function * F = CI->getCalledFunction();
+    if (!F)
+      return NULL;
+
+    const std::string & name = F->getName();
+    for (alloc_iterator it = alloc_begin(); it != alloc_end(); ++it) {
+      if ((*it)->isAllocSizeMayConstant(CI) && (*it)->getAllocCallName() == name) {
+        return (*it)->getAllocSize(CI);
+      }
+    }
+  }
+
+  return NULL;
+}
+
+}
+
Index: lib/Transforms/MemSafety/GEPChecks.cpp
===================================================================
--- lib/Transforms/MemSafety/GEPChecks.cpp	(revision 0)
+++ lib/Transforms/MemSafety/GEPChecks.cpp	(revision 0)
@@ -0,0 +1,159 @@
+//===- GEPChecks.cpp - Insert GEP run-time checks ------------------------- --//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This pass instruments GEPs with run-time checks to ensure safe array and
+// structure indexing.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "safecode"
+
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/MemSafety/GEPChecks.h"
+#include "llvm/Transforms/MemSafety/Utility.h"
+
+namespace llvm {
+
+char InsertGEPChecks::ID = 0;
+
+static RegisterPass<InsertGEPChecks>
+X ("gepchecks", "Insert GEP run-time checks");
+
+//
+// Command Line Options
+//
+
+// Disable checks on pure structure indexing
+cl::opt<bool> DisableStructChecks ("disable-structgepchecks", cl::Hidden,
+                                   cl::init(false),
+                                   cl::desc("Disable Struct GEP Checks"));
+
+// Pass Statistics
+namespace {
+  STATISTIC (GEPChecks, "Bounds Checks Added");
+#if 0
+  STATISTIC (SafeGEP,   "GEPs proven safe by SAFECode");
+#endif
+}
+
+//
+// Method: visitGetElementPtrInst()
+//
+// Description:
+//  This method checks to see if the specified GEP is safe.  If it cannot prove
+//  it safe, it then adds a run-time check for it.
+//
+void
+InsertGEPChecks::visitGetElementPtrInst (GetElementPtrInst & GEP) {
+  //
+  // Determine if the GEP is safe.  If it is, then don't do anything.
+  //
+#if 0
+  if (abcPass->isGEPSafe(&GEP)) {
+    ++SafeGEP;
+    return;
+  }
+#endif
+
+  //
+  // If this only indexes into a structure, ignore it.
+  //
+  if (DisableStructChecks && indexesStructsOnly (&GEP)) {
+    return;
+  }
+
+  //
+  // Get the function in which the GEP instruction lives.
+  //
+  Value * PH = ConstantPointerNull::get (getVoidPtrType(GEP.getContext()));
+  BasicBlock::iterator InsertPt = &GEP;
+  ++InsertPt;
+  Instruction * ResultPtr = castTo (&GEP,
+                                    getVoidPtrType(GEP.getContext()),
+                                    GEP.getName() + ".cast",
+                                    InsertPt);
+
+  //
+  // Make this an actual cast instruction; it will make it easier to update
+  // DSA.
+  //
+  Value * SrcPtr = castTo (GEP.getPointerOperand(),
+                           getVoidPtrType(GEP.getContext()),
+                           GEP.getName()+".cast",
+                           InsertPt);
+
+  //
+  // Create the call to the run-time check.
+  //
+  std::vector<Value *> args(1, PH);
+  args.push_back (SrcPtr);
+  args.push_back (ResultPtr);
+  CallInst::Create (PoolCheckArrayUI, args, "", InsertPt);
+
+  //
+  // Update the statistics.
+  //
+  ++GEPChecks;
+  return;
+}
+
+//
+// Method: doInitialization()
+//
+// Description:
+//  Perform module-level initialization before the pass is run.  For this
+//  pass, we need to create a function prototype for the GEP check function.
+//
+// Inputs:
+//  M - A reference to the LLVM module to modify.
+//
+// Return value:
+//  true - This LLVM module has been modified.
+//
+bool
+InsertGEPChecks::doInitialization (Module & M) {
+  //
+  // Create a function prototype for the function that performs incomplete
+  // pointer arithmetic (GEP) checks.
+  //
+  Type * VoidPtrTy = getVoidPtrType (M.getContext());
+  M.getOrInsertFunction ("boundscheckui",
+                         VoidPtrTy,
+                         VoidPtrTy,
+                         VoidPtrTy,
+                         VoidPtrTy,
+                         NULL);
+  return true;
+}
+
+bool
+InsertGEPChecks::runOnFunction (Function & F) {
+  //
+  // Get pointers to required analysis passes.
+  //
+  TD      = &getAnalysis<TargetData>();
+#if 0
+  abcPass = &getAnalysis<ArrayBoundsCheckGroup>();
+#endif
+
+  //
+  // Get a pointer to the run-time check function.
+  //
+  PoolCheckArrayUI = F.getParent()->getFunction ("boundscheckui");
+
+  //
+  // Visit all of the instructions in the function.
+  //
+  visit (F);
+  return true;
+}
+
+}
+
Index: lib/Transforms/MemSafety/LoadStoreChecks.cpp
===================================================================
--- lib/Transforms/MemSafety/LoadStoreChecks.cpp	(revision 0)
+++ lib/Transforms/MemSafety/LoadStoreChecks.cpp	(revision 0)
@@ -0,0 +1,138 @@
+//===- LoadStoreChecks.cpp - Insert load/store run-time checks ------------ --//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This pass instruments loads and stores with run-time checks to ensure memory
+// safety.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "safecode"
+
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Constants.h"
+#include "llvm/Transforms/MemSafety/LoadStoreChecks.h"
+#include "llvm/Transforms/MemSafety/Utility.h"
+
+namespace llvm {
+
+char InsertLSChecks::ID = 0;
+
+static RegisterPass<InsertLSChecks>
+X ("lschecks", "Insert load/store run-time checks");
+
+// Pass Statistics
+namespace {
+  STATISTIC (LSChecks, "Load/Store Checks Added");
+}
+
+//
+// Method: visitLoadInst()
+//
+// Description:
+//  Place a run-time check on a load instruction.
+//
+void
+InsertLSChecks::visitLoadInst (LoadInst & LI) {
+  //
+  // Create an STL container with the arguments.
+  // The first argument is the pool handle (which is a NULL pointer).
+  // The second argument is the pointer to check.
+  //
+  std::vector<Value *> args;
+  LLVMContext & Context = LI.getContext();
+  args.push_back(ConstantPointerNull::get (getVoidPtrType(Context)));
+  args.push_back(castTo (LI.getPointerOperand(), getVoidPtrType(Context), &LI));
+
+  //
+  // Create the call to the run-time check.  Place it *before* the load
+  // instruction.
+  //
+  CallInst::Create (PoolCheckUI, args, "", &LI);
+
+  //
+  // Update the statistics.
+  //
+  ++LSChecks;
+  return;
+}
+
+//
+// Method: visitStoreInst()
+//
+// Description:
+//  Place a run-time check on a store instruction.
+//
+void
+InsertLSChecks::visitStoreInst (StoreInst & SI) {
+  //
+  // Create an STL container with the arguments.
+  // The first argument is the pool handle (which is a NULL pointer).
+  // The second argument is the pointer to check.
+  //
+  std::vector<Value *> args;
+  LLVMContext & Context = SI.getContext();
+  args.push_back(ConstantPointerNull::get (getVoidPtrType(Context)));
+  args.push_back(castTo (SI.getPointerOperand(), getVoidPtrType(Context), &SI));
+
+  //
+  // Create the call to the run-time check.  Place it *before* the store
+  // instruction.
+  //
+  CallInst::Create (PoolCheckUI, args, "", &SI);
+
+  //
+  // Update the statistics.
+  //
+  ++LSChecks;
+  return;
+}
+
+//
+// Method: doInitialization()
+//
+// Description:
+//  Perform module-level initialization before the pass is run.  For this
+//  pass, we need to create a function prototype for the load/store check
+//  function.
+//
+// Inputs:
+//  M - A reference to the LLVM module to modify.
+//
+// Return value:
+//  true - This LLVM module has been modified.
+//
+bool
+InsertLSChecks::doInitialization (Module & M) {
+  //
+  // Create a function prototype for the function that performs incomplete
+  // load/store checks.
+  //
+  Type * VoidTy  = Type::getVoidTy (M.getContext());
+  Type * VoidPtrTy = getVoidPtrType (M.getContext());
+  M.getOrInsertFunction ("poolcheckui", VoidTy, VoidPtrTy, VoidPtrTy, NULL);
+  return true;
+}
+
+bool
+InsertLSChecks::runOnFunction (Function & F) {
+  //
+  // Get a pointer to the run-time check function.
+  //
+  PoolCheckUI = F.getParent()->getFunction ("poolcheckui");
+  assert (PoolCheckUI && "Load/Store Check function has disappeared!\n");
+
+  //
+  // Visit all of the instructions in the function.
+  //
+  visit (F);
+  return true;
+}
+
+}
+
Index: lib/Transforms/Makefile
===================================================================
--- lib/Transforms/Makefile	(revision 135516)
+++ lib/Transforms/Makefile	(working copy)
@@ -8,7 +8,7 @@
 ##===----------------------------------------------------------------------===##
 
 LEVEL = ../..
-PARALLEL_DIRS = Utils Instrumentation Scalar InstCombine IPO Hello
+PARALLEL_DIRS = Utils Instrumentation Scalar InstCombine IPO Hello MemSafety
 
 include $(LEVEL)/Makefile.config
 
