Fix a couple issues with the JIT and multiple modules:
[oota-llvm.git] / lib / ExecutionEngine / JIT / JIT.cpp
index 848786f31489f70fedd1e31baa84e4a5b352b540..48286e915ee8698a94b2024e24e980a4f2b945ad 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     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 is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -52,25 +52,56 @@ using namespace llvm;
 extern void *__dso_handle __attribute__ ((__visibility__ ("hidden")));
 #endif
 
+namespace {
+
 static struct RegisterJIT {
   RegisterJIT() { JIT::Register(); }
 } JITRegistrator;
 
+}
+
 namespace llvm {
   void LinkInJIT() {
   }
 }
 
-JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji)
-  : ExecutionEngine(MP), TM(tm), TJI(tji), jitstate(MP) {
+#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.
+ExecutionEngine *ExecutionEngine::createJIT(ModuleProvider *MP,
+                                            std::string *ErrorStr,
+                                            JITMemoryManager *JMM) {
+  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);
+  return EE;
+}
+
+JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji,
+         JITMemoryManager *JMM)
+  : ExecutionEngine(MP), TM(tm), TJI(tji) {
   setTargetData(TM.getTargetData());
 
+  jitstate = new JITState(MP);
+
   // Initialize MCE
-  MCE = createEmitter(*this);
+  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
@@ -85,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,
@@ -178,6 +253,11 @@ GenericValue JIT::runFunction(Function *F,
     case Type::DoubleTyID:
       rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
       return rv;
+    case Type::X86_FP80TyID:
+    case Type::FP128TyID:
+    case Type::PPC_FP128TyID:
+      assert(0 && "long double not supported yet");
+      return rv;
     case Type::PointerTyID:
       return PTOGV(((void*(*)())(intptr_t)FPtr)());
     }
@@ -190,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.
@@ -205,30 +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(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>());
@@ -246,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);
   }
 }
@@ -263,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
@@ -288,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);
@@ -328,8 +422,8 @@ void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) {
     // actually initialize the global after current function has finished
     // compilation.
     const Type *GlobalType = GV->getType()->getElementType();
-    size_t S = getTargetData()->getTypeSize(GlobalType);
-    size_t A = getTargetData()->getPrefTypeAlignment(GlobalType);
+    size_t S = getTargetData()->getABITypeSize(GlobalType);
+    size_t A = getTargetData()->getPreferredAlignment(GV);
     if (A <= 8) {
       Ptr = malloc(S);
     } else {
@@ -339,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;