Use use_empty() instead of getNumUses(), avoiding a use list traversal.
[oota-llvm.git] / lib / ExecutionEngine / JIT / JIT.cpp
index 70ee114b7750380cc1b15e79f38d681fe45c8d5b..48286e915ee8698a94b2024e24e980a4f2b945ad 100644 (file)
@@ -52,15 +52,23 @@ using namespace llvm;
 extern void *__dso_handle __attribute__ ((__visibility__ ("hidden")));
 #endif
 
+namespace {
+
 static struct RegisterJIT {
   RegisterJIT() { JIT::Register(); }
 } JITRegistrator;
 
+}
+
 namespace llvm {
   void LinkInJIT() {
   }
 }
 
+#if defined (__GNUC__)
+extern "C" void __register_frame(void*);
+#endif
+
 /// createJIT - This is the factory method for creating a JIT for the current
 /// machine, it does not fall back to the interpreter.  This takes ownership
 /// of the module provider.
@@ -70,7 +78,11 @@ ExecutionEngine *ExecutionEngine::createJIT(ModuleProvider *MP,
   ExecutionEngine *EE = JIT::createJIT(MP, ErrorStr, JMM);
   if (!EE) return 0;
   
-  
+  // Register routine for informing unwinding runtime about new EH frames
+#if defined(__GNUC__)
+  EE->InstallExceptionTableRegister(__register_frame);
+#endif
+
   // Make sure we can resolve symbols in the program as well. The zero arg
   // to the function tells DynamicLibrary to load the program, not a library.
   sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr);
@@ -79,15 +91,17 @@ ExecutionEngine *ExecutionEngine::createJIT(ModuleProvider *MP,
 
 JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji,
          JITMemoryManager *JMM)
-  : ExecutionEngine(MP), TM(tm), TJI(tji), jitstate(MP) {
+  : ExecutionEngine(MP), TM(tm), TJI(tji) {
   setTargetData(TM.getTargetData());
 
+  jitstate = new JITState(MP);
+
   // Initialize MCE
   MCE = createEmitter(*this, JMM);
 
   // Add target data
   MutexGuard locked(lock);
-  FunctionPassManager &PM = jitstate.getPM(locked);
+  FunctionPassManager &PM = jitstate->getPM(locked);
   PM.add(new TargetData(*TM.getTargetData()));
 
   // Turn the machine code intermediate representation into bytes in memory that
@@ -102,10 +116,54 @@ JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji,
 }
 
 JIT::~JIT() {
+  delete jitstate;
   delete MCE;
   delete &TM;
 }
 
+/// addModuleProvider - Add a new ModuleProvider to the JIT.  If we previously
+/// removed the last ModuleProvider, we need re-initialize jitstate with a valid
+/// ModuleProvider.
+void JIT::addModuleProvider(ModuleProvider *MP) {
+  MutexGuard locked(lock);
+
+  if (Modules.empty()) {
+    assert(!jitstate && "jitstate should be NULL if Modules vector is empty!");
+
+    jitstate = new JITState(MP);
+
+    FunctionPassManager &PM = jitstate->getPM(locked);
+    PM.add(new TargetData(*TM.getTargetData()));
+
+    // Turn the machine code intermediate representation into bytes in memory
+    // that may be executed.
+    if (TM.addPassesToEmitMachineCode(PM, *MCE, false /*fast*/)) {
+      cerr << "Target does not support machine code emission!\n";
+      abort();
+    }
+    
+    // Initialize passes.
+    PM.doInitialization();
+  }
+  
+  ExecutionEngine::addModuleProvider(MP);
+}
+
+/// removeModuleProvider - If we are removing the last ModuleProvider, 
+/// invalidate the jitstate since the PassManager it contains references a
+/// released ModuleProvider.
+Module *JIT::removeModuleProvider(ModuleProvider *MP, std::string *E) {
+  Module *result = ExecutionEngine::removeModuleProvider(MP, E);
+  
+  MutexGuard locked(lock);
+  if (Modules.empty()) {
+    delete jitstate;
+    jitstate = 0;
+  }
+  
+  return result;
+}
+
 /// run - Start execution with the specified function and arguments.
 ///
 GenericValue JIT::runFunction(Function *F,
@@ -212,11 +270,11 @@ GenericValue JIT::runFunction(Function *F,
 
   // First, create the function.
   FunctionType *STy=FunctionType::get(RetTy, std::vector<const Type*>(), false);
-  Function *Stub = new Function(STy, Function::InternalLinkage, "",
-                                F->getParent());
+  Function *Stub = Function::Create(STy, Function::InternalLinkage, "",
+                                    F->getParent());
 
   // Insert a basic block.
-  BasicBlock *StubBB = new BasicBlock("", Stub);
+  BasicBlock *StubBB = BasicBlock::Create("", Stub);
 
   // Convert all of the GenericValue arguments over to constants.  Note that we
   // currently don't support varargs.
@@ -227,34 +285,39 @@ GenericValue JIT::runFunction(Function *F,
     const GenericValue &AV = ArgValues[i];
     switch (ArgTy->getTypeID()) {
     default: assert(0 && "Unknown argument type for function call!");
-    case Type::IntegerTyID: C = ConstantInt::get(AV.IntVal); break;
-    case Type::FloatTyID:   C = ConstantFP ::get(ArgTy, APFloat(AV.FloatVal));
-                            break;
-    case Type::DoubleTyID:  C = ConstantFP ::get(ArgTy, APFloat(AV.DoubleVal));
-                            break;
+    case Type::IntegerTyID:
+        C = ConstantInt::get(AV.IntVal);
+        break;
+    case Type::FloatTyID:
+        C = ConstantFP::get(APFloat(AV.FloatVal));
+        break;
+    case Type::DoubleTyID:
+        C = ConstantFP::get(APFloat(AV.DoubleVal));
+        break;
     case Type::PPC_FP128TyID:
     case Type::X86_FP80TyID:
-    case Type::FP128TyID:   C = ConstantFP ::get(ArgTy, APFloat(AV.IntVal));
-                            break;
+    case Type::FP128TyID:
+        C = ConstantFP::get(APFloat(AV.IntVal));
+        break;
     case Type::PointerTyID:
       void *ArgPtr = GVTOP(AV);
-      if (sizeof(void*) == 4) {
+      if (sizeof(void*) == 4)
         C = ConstantInt::get(Type::Int32Ty, (int)(intptr_t)ArgPtr);
-      } else {
+      else
         C = ConstantInt::get(Type::Int64Ty, (intptr_t)ArgPtr);
-      }
       C = ConstantExpr::getIntToPtr(C, ArgTy);  // Cast the integer to pointer
       break;
     }
     Args.push_back(C);
   }
 
-  CallInst *TheCall = new CallInst(F, Args.begin(), Args.end(), "", StubBB);
+  CallInst *TheCall = CallInst::Create(F, Args.begin(), Args.end(),
+                                       "", StubBB);
   TheCall->setTailCall();
   if (TheCall->getType() != Type::VoidTy)
-    new ReturnInst(TheCall, StubBB);             // Return result of the call.
+    ReturnInst::Create(TheCall, StubBB);    // Return result of the call.
   else
-    new ReturnInst(StubBB);                      // Just return void.
+    ReturnInst::Create(StubBB);             // Just return void.
 
   // Finally, return the value returned by our nullary stub function.
   return runFunction(Stub, std::vector<GenericValue>());
@@ -272,15 +335,15 @@ void JIT::runJITOnFunction(Function *F) {
 
   // JIT the function
   isAlreadyCodeGenerating = true;
-  jitstate.getPM(locked).run(*F);
+  jitstate->getPM(locked).run(*F);
   isAlreadyCodeGenerating = false;
 
   // If the function referred to a global variable that had not yet been
   // emitted, it allocates memory for the global, but doesn't emit it yet.  Emit
   // all of these globals now.
-  while (!jitstate.getPendingGlobals(locked).empty()) {
-    const GlobalVariable *GV = jitstate.getPendingGlobals(locked).back();
-    jitstate.getPendingGlobals(locked).pop_back();
+  while (!jitstate->getPendingGlobals(locked).empty()) {
+    const GlobalVariable *GV = jitstate->getPendingGlobals(locked).back();
+    jitstate->getPendingGlobals(locked).pop_back();
     EmitGlobalVariable(GV);
   }
 }
@@ -289,7 +352,6 @@ void JIT::runJITOnFunction(Function *F) {
 /// specified function, compiling it if neccesary.
 ///
 void *JIT::getPointerToFunction(Function *F) {
-  MutexGuard locked(lock);
 
   if (void *Addr = getPointerToGlobalIfAvailable(F))
     return Addr;   // Check if function already code gen'd
@@ -314,7 +376,13 @@ void *JIT::getPointerToFunction(Function *F) {
       abort();
     }
   }
+  
+  if (void *Addr = getPointerToGlobalIfAvailable(F)) {
+    return Addr;
+  }
 
+  MutexGuard locked(lock);
+  
   if (F->isDeclaration()) {
     void *Addr = getPointerToNamedFunction(F->getName());
     addGlobalMapping(F, Addr);
@@ -365,7 +433,7 @@ void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) {
       unsigned MisAligned = ((intptr_t)Ptr & (A-1));
       Ptr = (char*)Ptr + (MisAligned ? (A-MisAligned) : 0);
     }
-    jitstate.getPendingGlobals(locked).push_back(GV);
+    jitstate->getPendingGlobals(locked).push_back(GV);
   }
   addGlobalMapping(GV, Ptr);
   return Ptr;