about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
authorJiri Slaby <jirislaby@gmail.com>2017-02-22 16:10:21 +0100
committerJiri Slaby <jirislaby@gmail.com>2017-02-25 11:11:04 +0100
commit4c8fabc7de30e17ef116b8f413f3a973c29cb56c (patch)
tree29e23676c07a95e83c58b5bcb5f8fd4189efaf45
parent1b67624c3a2fc1ca6f60d0a2b0f675d046dbba76 (diff)
downloadklee-4c8fabc7de30e17ef116b8f413f3a973c29cb56c.tar.gz
llvm: stop using global context
It was marked as deprecated long time ago and finally removed in LLVM
3.9. Remove all uses of getGlobalContext and create our own context.
Propagate it all over the code then.

[v2] use ctx, not C as name

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
-rw-r--r--include/klee/Interpreter.h4
-rw-r--r--lib/Core/Executor.cpp13
-rw-r--r--lib/Core/Executor.h4
-rw-r--r--lib/Core/ExternalDispatcher.cpp20
-rw-r--r--lib/Core/ExternalDispatcher.h3
-rw-r--r--lib/Module/Checks.cpp19
-rw-r--r--lib/Module/IntrinsicCleaner.cpp11
-rw-r--r--lib/Module/KModule.cpp26
-rw-r--r--lib/Module/LowerSwitch.cpp4
-rw-r--r--lib/Module/ModuleUtil.cpp5
-rw-r--r--tools/klee/main.cpp31
11 files changed, 78 insertions, 62 deletions
diff --git a/include/klee/Interpreter.h b/include/klee/Interpreter.h
index ece84b2c..4c428994 100644
--- a/include/klee/Interpreter.h
+++ b/include/klee/Interpreter.h
@@ -18,6 +18,7 @@ struct KTest;
 
 namespace llvm {
 class Function;
+class LLVMContext;
 class Module;
 class raw_ostream;
 class raw_fd_ostream;
@@ -93,7 +94,8 @@ protected:
 public:
   virtual ~Interpreter() {}
 
-  static Interpreter *create(const InterpreterOptions &_interpreterOpts,
+  static Interpreter *create(llvm::LLVMContext &ctx,
+                             const InterpreterOptions &_interpreterOpts,
                              InterpreterHandler *ih);
 
   /// Register the module to be executed.  
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index 58603e7c..19a5e3f8 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -343,9 +343,10 @@ const char *Executor::TerminateReasonNames[] = {
   [ Unhandled ] = "xxx",
 };
 
-Executor::Executor(const InterpreterOptions &opts, InterpreterHandler *ih)
+Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts,
+    InterpreterHandler *ih)
     : Interpreter(opts), kmodule(0), interpreterHandler(ih), searcher(0),
-      externalDispatcher(new ExternalDispatcher()), statsTracker(0),
+      externalDispatcher(new ExternalDispatcher(ctx)), statsTracker(0),
       pathWriter(0), symPathWriter(0), specialFunctionHandler(0),
       processTree(0), replayKTest(0), replayPath(0), usingSeeds(0),
       atMemoryLimit(false), inhibitForking(false), haltExecution(false),
@@ -1552,7 +1553,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
 
       if (!isVoidReturn) {
         LLVM_TYPE_Q Type *t = caller->getType();
-        if (t != Type::getVoidTy(getGlobalContext())) {
+        if (t != Type::getVoidTy(i->getContext())) {
           // may need to do coercion due to bitcasts
           Expr::Width from = result->getWidth();
           Expr::Width to = getWidthForLLVMType(t);
@@ -3087,7 +3088,7 @@ void Executor::callExternalFunction(ExecutionState &state,
   }
 
   LLVM_TYPE_Q Type *resultType = target->inst->getType();
-  if (resultType != Type::getVoidTy(getGlobalContext())) {
+  if (resultType != Type::getVoidTy(function->getContext())) {
     ref<Expr> e = ConstantExpr::fromMemory((void*) args, 
                                            getWidthForLLVMType(resultType));
     bindLocal(target, state, e);
@@ -3756,7 +3757,7 @@ Expr::Width Executor::getWidthForLLVMType(LLVM_TYPE_Q llvm::Type *type) const {
 
 ///
 
-Interpreter *Interpreter::create(const InterpreterOptions &opts,
+Interpreter *Interpreter::create(LLVMContext &ctx, const InterpreterOptions &opts,
                                  InterpreterHandler *ih) {
-  return new Executor(opts, ih);
+  return new Executor(ctx, opts, ih);
 }
diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h
index 93d1443e..4970b8a0 100644
--- a/lib/Core/Executor.h
+++ b/lib/Core/Executor.h
@@ -41,6 +41,7 @@ namespace llvm {
   class Function;
   class GlobalValue;
   class Instruction;
+  class LLVMContext;
 #if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1)
   class TargetData;
 #else
@@ -434,7 +435,8 @@ private:
   void doDumpStates();
 
 public:
-  Executor(const InterpreterOptions &opts, InterpreterHandler *ie);
+  Executor(llvm::LLVMContext &ctx, const InterpreterOptions &opts,
+      InterpreterHandler *ie);
   virtual ~Executor();
 
   const InterpreterHandler& getHandler() {
diff --git a/lib/Core/ExternalDispatcher.cpp b/lib/Core/ExternalDispatcher.cpp
index ecc9912e..01c5f935 100644
--- a/lib/Core/ExternalDispatcher.cpp
+++ b/lib/Core/ExternalDispatcher.cpp
@@ -85,8 +85,8 @@ void *ExternalDispatcher::resolveSymbol(const std::string &name) {
   return addr;
 }
 
-ExternalDispatcher::ExternalDispatcher() {
-  dispatchModule = new Module("ExternalDispatcher", getGlobalContext());
+ExternalDispatcher::ExternalDispatcher(LLVMContext &ctx) {
+  dispatchModule = new Module("ExternalDispatcher", ctx);
 
   std::string error;
   executionEngine = ExecutionEngine::createJIT(dispatchModule, &error);
@@ -195,6 +195,7 @@ Function *ExternalDispatcher::createDispatcher(Function *target, Instruction *in
   if (!resolveSymbol(target->getName()))
     return 0;
 
+  LLVMContext &ctx = target->getContext();
   CallSite cs;
   if (inst->getOpcode()==Instruction::Call) {
     cs = CallSite(cast<CallInst>(inst));
@@ -206,20 +207,20 @@ Function *ExternalDispatcher::createDispatcher(Function *target, Instruction *in
 
   std::vector<LLVM_TYPE_Q Type*> nullary;
   
-  Function *dispatcher = Function::Create(FunctionType::get(Type::getVoidTy(getGlobalContext()), 
+  Function *dispatcher = Function::Create(FunctionType::get(Type::getVoidTy(ctx),
 							    nullary, false),
 					  GlobalVariable::ExternalLinkage, 
 					  "",
 					  dispatchModule);
 
 
-  BasicBlock *dBB = BasicBlock::Create(getGlobalContext(), "entry", dispatcher);
+  BasicBlock *dBB = BasicBlock::Create(ctx, "entry", dispatcher);
 
   // Get a Value* for &gTheArgsP, as an i64**.
   Instruction *argI64sp = 
-    new IntToPtrInst(ConstantInt::get(Type::getInt64Ty(getGlobalContext()), 
+    new IntToPtrInst(ConstantInt::get(Type::getInt64Ty(ctx),
                                       (uintptr_t) (void*) &gTheArgsP),
-                     PointerType::getUnqual(PointerType::getUnqual(Type::getInt64Ty(getGlobalContext()))),
+                     PointerType::getUnqual(PointerType::getUnqual(Type::getInt64Ty(ctx))),
                      "argsp", dBB);
   Instruction *argI64s = new LoadInst(argI64sp, "args", dBB); 
   
@@ -238,8 +239,7 @@ Function *ExternalDispatcher::createDispatcher(Function *target, Instruction *in
                                (*ai)->getType());
     Instruction *argI64p = 
       GetElementPtrInst::Create(argI64s, 
-                                ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 
-                                                 idx), 
+                                ConstantInt::get(Type::getInt32Ty(ctx), idx),
                                 "", dBB);
 
     Instruction *argp = new BitCastInst(argI64p, PointerType::getUnqual(argTy),
@@ -260,14 +260,14 @@ Function *ExternalDispatcher::createDispatcher(Function *target, Instruction *in
 #else
   Instruction *result = CallInst::Create(dispatchTarget, args, args+i, "", dBB);
 #endif
-  if (result->getType() != Type::getVoidTy(getGlobalContext())) {
+  if (result->getType() != Type::getVoidTy(ctx)) {
     Instruction *resp = 
       new BitCastInst(argI64s, PointerType::getUnqual(result->getType()), 
                       "", dBB);
     new StoreInst(result, resp, dBB);
   }
 
-  ReturnInst::Create(getGlobalContext(), dBB);
+  ReturnInst::Create(ctx, dBB);
 
   delete[] args;
 
diff --git a/lib/Core/ExternalDispatcher.h b/lib/Core/ExternalDispatcher.h
index d8d9dc58..94363bab 100644
--- a/lib/Core/ExternalDispatcher.h
+++ b/lib/Core/ExternalDispatcher.h
@@ -17,6 +17,7 @@
 namespace llvm {
   class ExecutionEngine;
   class Instruction;
+  class LLVMContext;
   class Function;
   class FunctionType;
   class Module;
@@ -35,7 +36,7 @@ namespace klee {
     bool runProtectedCall(llvm::Function *f, uint64_t *args);
     
   public:
-    ExternalDispatcher();
+    ExternalDispatcher(llvm::LLVMContext &ctx);
     ~ExternalDispatcher();
 
     /* Call the given function using the parameter passing convention of
diff --git a/lib/Module/Checks.cpp b/lib/Module/Checks.cpp
index 7d9b7284..44b35e6e 100644
--- a/lib/Module/Checks.cpp
+++ b/lib/Module/Checks.cpp
@@ -53,6 +53,7 @@ char DivCheckPass::ID;
 
 bool DivCheckPass::runOnModule(Module &M) { 
   Function *divZeroCheckFunction = 0;
+  LLVMContext &ctx = M.getContext();
 
   bool moduleChanged = false;
   
@@ -67,7 +68,7 @@ bool DivCheckPass::runOnModule(Module &M) {
             
             CastInst *denominator =
               CastInst::CreateIntegerCast(i->getOperand(1),
-                                          Type::getInt64Ty(getGlobalContext()),
+                                          Type::getInt64Ty(ctx),
                                           false,  /* sign doesn't matter */
                                           "int_cast_to_i64",
                                           i);
@@ -75,8 +76,8 @@ bool DivCheckPass::runOnModule(Module &M) {
             // Lazily bind the function to avoid always importing it.
             if (!divZeroCheckFunction) {
               Constant *fc = M.getOrInsertFunction("klee_div_zero_check", 
-                                                   Type::getVoidTy(getGlobalContext()), 
-                                                   Type::getInt64Ty(getGlobalContext()), 
+                                                   Type::getVoidTy(ctx),
+                                                   Type::getInt64Ty(ctx),
                                                    NULL);
               divZeroCheckFunction = cast<Function>(fc);
             }
@@ -100,6 +101,7 @@ char OvershiftCheckPass::ID;
 
 bool OvershiftCheckPass::runOnModule(Module &M) {
   Function *overshiftCheckFunction = 0;
+  LLVMContext &ctx = M.getContext();
 
   bool moduleChanged = false;
 
@@ -118,12 +120,13 @@ bool OvershiftCheckPass::runOnModule(Module &M) {
             // Determine bit width of first operand
             uint64_t bitWidth=i->getOperand(0)->getType()->getScalarSizeInBits();
 
-            ConstantInt *bitWidthC = ConstantInt::get(Type::getInt64Ty(getGlobalContext()),bitWidth,false);
+            ConstantInt *bitWidthC = ConstantInt::get(Type::getInt64Ty(ctx),
+		bitWidth, false);
             args.push_back(bitWidthC);
 
             CastInst *shift =
               CastInst::CreateIntegerCast(i->getOperand(1),
-                                          Type::getInt64Ty(getGlobalContext()),
+                                          Type::getInt64Ty(ctx),
                                           false,  /* sign doesn't matter */
                                           "int_cast_to_i64",
                                           i);
@@ -133,9 +136,9 @@ bool OvershiftCheckPass::runOnModule(Module &M) {
             // Lazily bind the function to avoid always importing it.
             if (!overshiftCheckFunction) {
               Constant *fc = M.getOrInsertFunction("klee_overshift_check",
-                                                   Type::getVoidTy(getGlobalContext()),
-                                                   Type::getInt64Ty(getGlobalContext()),
-                                                   Type::getInt64Ty(getGlobalContext()),
+                                                   Type::getVoidTy(ctx),
+                                                   Type::getInt64Ty(ctx),
+                                                   Type::getInt64Ty(ctx),
                                                    NULL);
               overshiftCheckFunction = cast<Function>(fc);
             }
diff --git a/lib/Module/IntrinsicCleaner.cpp b/lib/Module/IntrinsicCleaner.cpp
index 54582e69..3f7644af 100644
--- a/lib/Module/IntrinsicCleaner.cpp
+++ b/lib/Module/IntrinsicCleaner.cpp
@@ -70,6 +70,7 @@ bool IntrinsicCleanerPass::runOnModule(Module &M) {
 bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) {
   bool dirty = false;
   bool block_split=false;
+  LLVMContext &ctx = M.getContext();
   
 #if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1)
   unsigned WordSize = TargetData.getPointerSizeInBits() / 8;
@@ -97,18 +98,18 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) {
         Value *src = ii->getArgOperand(1);
 
         if (WordSize == 4) {
-          Type *i8pp = PointerType::getUnqual(PointerType::getUnqual(Type::getInt8Ty(getGlobalContext())));
+          Type *i8pp = PointerType::getUnqual(PointerType::getUnqual(Type::getInt8Ty(ctx)));
           Value *castedDst = CastInst::CreatePointerCast(dst, i8pp, "vacopy.cast.dst", ii);
           Value *castedSrc = CastInst::CreatePointerCast(src, i8pp, "vacopy.cast.src", ii);
           Value *load = new LoadInst(castedSrc, "vacopy.read", ii);
           new StoreInst(load, castedDst, false, ii);
         } else {
           assert(WordSize == 8 && "Invalid word size!");
-          Type *i64p = PointerType::getUnqual(Type::getInt64Ty(getGlobalContext()));
+          Type *i64p = PointerType::getUnqual(Type::getInt64Ty(ctx));
           Value *pDst = CastInst::CreatePointerCast(dst, i64p, "vacopy.cast.dst", ii);
           Value *pSrc = CastInst::CreatePointerCast(src, i64p, "vacopy.cast.src", ii);
           Value *val = new LoadInst(pSrc, std::string(), ii); new StoreInst(val, pDst, ii);
-          Value *off = ConstantInt::get(Type::getInt64Ty(getGlobalContext()), 1);
+          Value *off = ConstantInt::get(Type::getInt64Ty(ctx), 1);
           pDst = GetElementPtrInst::Create(pDst, off, std::string(), ii);
           pSrc = GetElementPtrInst::Create(pSrc, off, std::string(), ii);
           val = new LoadInst(pSrc, std::string(), ii); new StoreInst(val, pDst, ii);
@@ -223,12 +224,12 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) {
         // a call of the abort() function.
         Function *F = cast<Function>(
           M.getOrInsertFunction(
-            "abort", Type::getVoidTy(getGlobalContext()), NULL));
+            "abort", Type::getVoidTy(ctx), NULL));
         F->setDoesNotReturn();
         F->setDoesNotThrow();
 
         CallInst::Create(F, Twine(), ii);
-        new UnreachableInst(getGlobalContext(), ii);
+        new UnreachableInst(ctx, ii);
 
         ii->eraseFromParent();
 
diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp
index 57346a31..3259873e 100644
--- a/lib/Module/KModule.cpp
+++ b/lib/Module/KModule.cpp
@@ -144,12 +144,12 @@ static Function *getStubFunctionForCtorList(Module *m,
   
   std::vector<LLVM_TYPE_Q Type*> nullary;
 
-  Function *fn = Function::Create(FunctionType::get(Type::getVoidTy(getGlobalContext()), 
+  Function *fn = Function::Create(FunctionType::get(Type::getVoidTy(m->getContext()),
 						    nullary, false),
 				  GlobalVariable::InternalLinkage, 
 				  name,
                               m);
-  BasicBlock *bb = BasicBlock::Create(getGlobalContext(), "entry", fn);
+  BasicBlock *bb = BasicBlock::Create(m->getContext(), "entry", fn);
   
   // From lli:
   // Should be an array of '{ int, void ()* }' structs.  The first value is
@@ -174,7 +174,7 @@ static Function *getStubFunctionForCtorList(Module *m,
     }
   }
   
-  ReturnInst::Create(getGlobalContext(), bb);
+  ReturnInst::Create(m->getContext(), bb);
 
   return fn;
 }
@@ -241,11 +241,13 @@ void KModule::addInternalFunction(const char* functionName){
 
 void KModule::prepare(const Interpreter::ModuleOptions &opts,
                       InterpreterHandler *ih) {
+  LLVMContext &ctx = module->getContext();
+
   if (!MergeAtExit.empty()) {
     Function *mergeFn = module->getFunction("klee_merge");
     if (!mergeFn) {
       LLVM_TYPE_Q llvm::FunctionType *Ty = 
-        FunctionType::get(Type::getVoidTy(getGlobalContext()), 
+        FunctionType::get(Type::getVoidTy(ctx),
                           std::vector<LLVM_TYPE_Q Type*>(), false);
       mergeFn = Function::Create(Ty, GlobalVariable::ExternalLinkage,
 				 "klee_merge",
@@ -264,16 +266,16 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts,
                    name.c_str());
       }
 
-      BasicBlock *exit = BasicBlock::Create(getGlobalContext(), "exit", f);
+      BasicBlock *exit = BasicBlock::Create(ctx, "exit", f);
       PHINode *result = 0;
-      if (f->getReturnType() != Type::getVoidTy(getGlobalContext()))
+      if (f->getReturnType() != Type::getVoidTy(ctx))
 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 0)
         result = PHINode::Create(f->getReturnType(), 0, "retval", exit);
 #else
 		result = PHINode::Create(f->getReturnType(), "retval", exit);
 #endif
       CallInst::Create(mergeFn, "", exit);
-      ReturnInst::Create(getGlobalContext(), result, exit);
+      ReturnInst::Create(ctx, result, exit);
 
       llvm::errs() << "KLEE: adding klee_merge at exit of: " << name << "\n";
       for (llvm::Function::iterator bbit = f->begin(), bbie = f->end(); 
@@ -317,19 +319,19 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts,
   // by name. We only add them if such a function doesn't exist to
   // avoid creating stale uses.
 
-  LLVM_TYPE_Q llvm::Type *i8Ty = Type::getInt8Ty(getGlobalContext());
+  LLVM_TYPE_Q llvm::Type *i8Ty = Type::getInt8Ty(ctx);
   forceImport(module, "memcpy", PointerType::getUnqual(i8Ty),
               PointerType::getUnqual(i8Ty),
               PointerType::getUnqual(i8Ty),
-              targetData->getIntPtrType(getGlobalContext()), (Type*) 0);
+              targetData->getIntPtrType(ctx), (Type*) 0);
   forceImport(module, "memmove", PointerType::getUnqual(i8Ty),
               PointerType::getUnqual(i8Ty),
               PointerType::getUnqual(i8Ty),
-              targetData->getIntPtrType(getGlobalContext()), (Type*) 0);
+              targetData->getIntPtrType(ctx), (Type*) 0);
   forceImport(module, "memset", PointerType::getUnqual(i8Ty),
               PointerType::getUnqual(i8Ty),
-              Type::getInt32Ty(getGlobalContext()),
-              targetData->getIntPtrType(getGlobalContext()), (Type*) 0);
+              Type::getInt32Ty(ctx),
+              targetData->getIntPtrType(ctx), (Type*) 0);
 #endif
   // FIXME: Missing force import for various math functions.
 
diff --git a/lib/Module/LowerSwitch.cpp b/lib/Module/LowerSwitch.cpp
index a98b84ad..7f28748a 100644
--- a/lib/Module/LowerSwitch.cpp
+++ b/lib/Module/LowerSwitch.cpp
@@ -66,7 +66,7 @@ void LowerSwitchPass::switchConvert(CaseItr begin, CaseItr end,
   
   // iterate through all the cases, creating a new BasicBlock for each
   for (CaseItr it = begin; it < end; ++it) {
-    BasicBlock *newBlock = BasicBlock::Create(getGlobalContext(), "NodeBlock");
+    BasicBlock *newBlock = BasicBlock::Create(F->getContext(), "NodeBlock");
     Function::iterator FI = origBlock;
     F->getBasicBlockList().insert(++FI, newBlock);
     
@@ -102,7 +102,7 @@ void LowerSwitchPass::processSwitchInst(SwitchInst *SI) {
 
   // Create a new, empty default block so that the new hierarchy of
   // if-then statements go to this and the PHI nodes are happy.
-  BasicBlock* newDefault = BasicBlock::Create(getGlobalContext(), "newDefault");
+  BasicBlock* newDefault = BasicBlock::Create(F->getContext(), "newDefault");
 
   F->getBasicBlockList().insert(defaultBlock, newDefault);
   BranchInst::Create(defaultBlock, newDefault);
diff --git a/lib/Module/ModuleUtil.cpp b/lib/Module/ModuleUtil.cpp
index 2cd41c89..94a37e08 100644
--- a/lib/Module/ModuleUtil.cpp
+++ b/lib/Module/ModuleUtil.cpp
@@ -248,7 +248,8 @@ static bool linkBCA(object::Archive* archive, Module* composite, std::string& er
       if (buff)
       {
         // FIXME: Maybe load bitcode file lazily? Then if we need to link, materialise the module
-        Result = ParseBitcodeFile(buff.get(), getGlobalContext(), &errorMessage);
+        Result = ParseBitcodeFile(buff.get(), composite->getContext(),
+	    &errorMessage);
 
         if(!Result)
         {
@@ -378,7 +379,7 @@ Module *klee::linkWithLibrary(Module *module,
 
   sys::fs::file_magic magic = sys::fs::identify_magic(Buffer->getBuffer());
 
-  LLVMContext &Context = getGlobalContext();
+  LLVMContext &Context = module->getContext();
   std::string ErrorMessage;
 
   if (magic == sys::fs::file_magic::bitcode) {
diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp
index e95522a0..505d259c 100644
--- a/tools/klee/main.cpp
+++ b/tools/klee/main.cpp
@@ -689,11 +689,12 @@ static int initEnv(Module *mainModule) {
 
   /* Insert void klee_init_env(int* argc, char*** argv) */
   std::vector<const Type*> params;
-  params.push_back(Type::getInt32Ty(getGlobalContext()));
-  params.push_back(Type::getInt32Ty(getGlobalContext()));
+  LLVMContext &ctx = mainModule->getContext();
+  params.push_back(Type::getInt32Ty(ctx));
+  params.push_back(Type::getInt32Ty(ctx));
   Function* initEnvFn =
     cast<Function>(mainModule->getOrInsertFunction("klee_init_env",
-                                                   Type::getVoidTy(getGlobalContext()),
+                                                   Type::getVoidTy(ctx),
                                                    argcPtr->getType(),
                                                    argvPtr->getType(),
                                                    NULL));
@@ -1032,6 +1033,7 @@ static void replaceOrRenameFunction(llvm::Module *module,
   }
 }
 static llvm::Module *linkWithUclibc(llvm::Module *mainModule, StringRef libDir) {
+  LLVMContext &ctx = mainModule->getContext();
   // Ensure that klee-uclibc exists
   SmallString<128> uclibcBCA(libDir);
   llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_NAME);
@@ -1044,13 +1046,13 @@ static llvm::Module *linkWithUclibc(llvm::Module *mainModule, StringRef libDir)
   Function *f;
   // force import of __uClibc_main
   mainModule->getOrInsertFunction("__uClibc_main",
-                                  FunctionType::get(Type::getVoidTy(getGlobalContext()),
+                                  FunctionType::get(Type::getVoidTy(ctx),
                                                std::vector<LLVM_TYPE_Q Type*>(),
                                                     true));
 
   // force various imports
   if (WithPOSIXRuntime) {
-    LLVM_TYPE_Q llvm::Type *i8Ty = Type::getInt8Ty(getGlobalContext());
+    LLVM_TYPE_Q llvm::Type *i8Ty = Type::getInt8Ty(ctx);
     mainModule->getOrInsertFunction("realpath",
                                     PointerType::getUnqual(i8Ty),
                                     PointerType::getUnqual(i8Ty),
@@ -1060,12 +1062,12 @@ static llvm::Module *linkWithUclibc(llvm::Module *mainModule, StringRef libDir)
                                     PointerType::getUnqual(i8Ty),
                                     NULL);
     mainModule->getOrInsertFunction("__fgetc_unlocked",
-                                    Type::getInt32Ty(getGlobalContext()),
+                                    Type::getInt32Ty(ctx),
                                     PointerType::getUnqual(i8Ty),
                                     NULL);
     mainModule->getOrInsertFunction("__fputc_unlocked",
-                                    Type::getInt32Ty(getGlobalContext()),
-                                    Type::getInt32Ty(getGlobalContext()),
+                                    Type::getInt32Ty(ctx),
+                                    Type::getInt32Ty(ctx),
                                     PointerType::getUnqual(i8Ty),
                                     NULL);
   }
@@ -1130,11 +1132,11 @@ static llvm::Module *linkWithUclibc(llvm::Module *mainModule, StringRef libDir)
   std::vector<LLVM_TYPE_Q Type*> fArgs;
   fArgs.push_back(ft->getParamType(1)); // argc
   fArgs.push_back(ft->getParamType(2)); // argv
-  Function *stub = Function::Create(FunctionType::get(Type::getInt32Ty(getGlobalContext()), fArgs, false),
+  Function *stub = Function::Create(FunctionType::get(Type::getInt32Ty(ctx), fArgs, false),
                                     GlobalVariable::ExternalLinkage,
                                     EntryPoint,
                                     mainModule);
-  BasicBlock *bb = BasicBlock::Create(getGlobalContext(), "entry", stub);
+  BasicBlock *bb = BasicBlock::Create(ctx, "entry", stub);
 
   std::vector<llvm::Value*> args;
   args.push_back(llvm::ConstantExpr::getBitCast(userMainFn,
@@ -1151,7 +1153,7 @@ static llvm::Module *linkWithUclibc(llvm::Module *mainModule, StringRef libDir)
   CallInst::Create(uclibcMainFn, args.begin(), args.end(), "", bb);
 #endif
 
-  new UnreachableInst(getGlobalContext(), bb);
+  new UnreachableInst(ctx, bb);
 
   klee_message("NOTE: Using klee-uclibc : %s", uclibcBCA.c_str());
   return mainModule;
@@ -1236,6 +1238,7 @@ int main(int argc, char **argv, char **envp) {
 
   // Load the bytecode...
   std::string ErrorMsg;
+  LLVMContext ctx;
   Module *mainModule = 0;
 #if LLVM_VERSION_CODE < LLVM_VERSION(3, 5)
   OwningPtr<MemoryBuffer> BufferPtr;
@@ -1245,7 +1248,7 @@ int main(int argc, char **argv, char **envp) {
                ec.message().c_str());
   }
 
-  mainModule = getLazyBitcodeModule(BufferPtr.get(), getGlobalContext(), &ErrorMsg);
+  mainModule = getLazyBitcodeModule(BufferPtr.get(), ctx, &ErrorMsg);
 
   if (mainModule) {
     if (mainModule->MaterializeAllPermanently(&ErrorMsg)) {
@@ -1262,7 +1265,7 @@ int main(int argc, char **argv, char **envp) {
     klee_error("error loading program '%s': %s", InputFile.c_str(),
                Buffer.getError().message().c_str());
 
-  auto mainModuleOrError = getLazyBitcodeModule(Buffer->get(), getGlobalContext());
+  auto mainModuleOrError = getLazyBitcodeModule(Buffer->get(), ctx);
 
   if (!mainModuleOrError) {
     klee_error("error loading program '%s': %s", InputFile.c_str(),
@@ -1387,7 +1390,7 @@ int main(int argc, char **argv, char **envp) {
   IOpts.MakeConcreteSymbolic = MakeConcreteSymbolic;
   KleeHandler *handler = new KleeHandler(pArgc, pArgv);
   Interpreter *interpreter =
-    theInterpreter = Interpreter::create(IOpts, handler);
+    theInterpreter = Interpreter::create(ctx, IOpts, handler);
   handler->setInterpreter(interpreter);
 
   for (int i=0; i<argc; i++) {