Resolve BB references with relocation.
[oota-llvm.git] / lib / ExecutionEngine / JIT / JITEmitter.cpp
index 2a62bd3557c5f95c848fa42592090826cf8138f3..dc9ba28371e669fb1d0f226d04cd64306ccdbc90 100644 (file)
@@ -392,12 +392,14 @@ JITMemoryManager::JITMemoryManager(bool useGOT) {
 
   // Allocate the GOT.
   GOTBase = NULL;
-  if (useGOT) GOTBase = (unsigned char*)malloc(sizeof(void*) * 8192);
+  if (useGOT) GOTBase = new unsigned char[sizeof(void*) * 8192];
 }
 
 JITMemoryManager::~JITMemoryManager() {
   for (unsigned i = 0, e = Blocks.size(); i != e; ++i)
     sys::Memory::ReleaseRWX(Blocks[i]);
+  
+  delete[] GOTBase;
   Blocks.clear();
 }
 
@@ -412,17 +414,17 @@ unsigned char *JITMemoryManager::allocateStub(unsigned StubSize) {
 }
 
 sys::MemoryBlock JITMemoryManager::getNewMemoryBlock(unsigned size) {
-  try {
-    // Allocate a new block close to the last one.
-    const sys::MemoryBlock *BOld = Blocks.empty() ? 0 : &Blocks.front();
-    sys::MemoryBlock B = sys::Memory::AllocateRWX(size, BOld);
-    Blocks.push_back(B);
-    return B;
-  } catch (std::string &err) {
+  // Allocate a new block close to the last one.
+  const sys::MemoryBlock *BOld = Blocks.empty() ? 0 : &Blocks.front();
+  std::string ErrMsg;
+  sys::MemoryBlock B = sys::Memory::AllocateRWX(size, BOld, &ErrMsg);
+  if (B.base() == 0) {
     std::cerr << "Allocation failed when allocating new memory in the JIT\n";
-    std::cerr << err << "\n";
+    std::cerr << ErrMsg << "\n";
     abort();
   }
+  Blocks.push_back(B);
+  return B;
 }
 
 //===----------------------------------------------------------------------===//
@@ -492,7 +494,7 @@ namespace {
       MutexGuard locked(TheJIT->lock);
       /// Get the target-specific JIT resolver function.
       state.getStubToFunctionMap(locked)[Location] = F;
-      return (void*)LazyResolverFn;
+      return (void*)(intptr_t)LazyResolverFn;
     }
 
     /// getGOTIndexForAddress - Return a new or existing index in the GOT for
@@ -514,6 +516,20 @@ static JITResolver &getJITResolver(MachineCodeEmitter *MCE = 0) {
   return TheJITResolver;
 }
 
+#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
+    defined(__APPLE__)
+extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
+#endif
+
+/// synchronizeICache - On some targets, the JIT emitted code must be
+/// explicitly refetched to ensure correct execution.
+static void synchronizeICache(const void *Addr, size_t len) {
+#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
+    defined(__APPLE__)
+  sys_icache_invalidate(Addr, len);
+#endif
+}
+
 /// getFunctionStub - This returns a pointer to a function stub, creating
 /// one on demand as needed.
 void *JITResolver::getFunctionStub(Function *F) {
@@ -525,7 +541,7 @@ void *JITResolver::getFunctionStub(Function *F) {
 
   // Call the lazy resolver function unless we already KNOW it is an external
   // function, in which case we just skip the lazy resolution step.
-  void *Actual = (void*)LazyResolverFn;
+  void *Actual = (void*)(intptr_t)LazyResolverFn;
   if (F->isExternal() && F->hasExternalLinkage())
     Actual = TheJIT->getPointerToFunction(F);
 
@@ -533,13 +549,16 @@ void *JITResolver::getFunctionStub(Function *F) {
   // resolver function.
   Stub = TheJIT->getJITInfo().emitFunctionStub(Actual, MCE);
 
-  if (Actual != (void*)LazyResolverFn) {
+  if (Actual != (void*)(intptr_t)LazyResolverFn) {
     // If we are getting the stub for an external function, we really want the
     // address of the stub in the GlobalAddressMap for the JIT, not the address
     // of the external function.
     TheJIT->updateGlobalMapping(F, Stub);
   }
 
+  // Invalidate the icache if necessary.
+  synchronizeICache(Stub, MCE.getCurrentPCValue()-(intptr_t)Stub);
+
   DEBUG(std::cerr << "JIT: Stub emitted at [" << Stub << "] for function '"
                   << F->getName() << "'\n");
 
@@ -557,6 +576,10 @@ void *JITResolver::getExternalFunctionStub(void *FnAddr) {
   if (Stub) return Stub;
 
   Stub = TheJIT->getJITInfo().emitFunctionStub(FnAddr, MCE);
+
+  // Invalidate the icache if necessary.
+  synchronizeICache(Stub, MCE.getCurrentPCValue()-(intptr_t)Stub);
+
   DEBUG(std::cerr << "JIT: Stub emitted at [" << Stub
         << "] for external function at '" << FnAddr << "'\n");
   return Stub;
@@ -745,7 +768,7 @@ void JITEmitter::startFunction(MachineFunction &F) {
   // About to start emitting the machine code for the function.
   emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
   TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr);
-  
+
   MBBLocations.clear();
 }
 
@@ -758,8 +781,14 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
   
   emitJumpTableInfo(F.getJumpTableInfo());
   
-  MemMgr.endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
-  NumBytes += getCurrentPCOffset();
+  // FnStart is the start of the text, not the start of the constant pool and
+  // other per-function data.
+  unsigned char *FnStart =
+    (unsigned char *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction());
+  unsigned char *FnEnd   = CurBufferPtr;
+  
+  MemMgr.endFunctionBody(F.getFunction(), BufferBegin, FnEnd);
+  NumBytes += FnEnd-FnStart;
 
   if (!Relocations.empty()) {
     NumRelos += Relocations.size();
@@ -778,9 +807,13 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
         ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
                                        BufferBegin+MR.getMachineCodeOffset(),
                                        MR.doesntNeedFunctionStub());
-      } else {
-        assert(MR.isConstantPoolIndex());
+      } else if (MR.isBasicBlock()) {
+        ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock());
+      } else if (MR.isConstantPoolIndex()){
         ResultPtr=(void*)getConstantPoolEntryAddress(MR.getConstantPoolIndex());
+      } else {
+        assert(MR.isJumpTableIndex());
+        ResultPtr=(void*)getJumpTableEntryAddress(MR.getJumpTableIndex());
       }
 
       MR.setResultPointer(ResultPtr);
@@ -813,9 +846,12 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
     }
   }
 
-  DEBUG(std::cerr << "JIT: Finished CodeGen of [" << (void*)BufferBegin
+  // Invalidate the icache if necessary.
+  synchronizeICache(FnStart, FnEnd-FnStart);
+
+  DEBUG(std::cerr << "JIT: Finished CodeGen of [" << (void*)FnStart
                   << "] Function: " << F.getFunction()->getName()
-                  << ": " << getCurrentPCOffset() << " bytes of text, "
+                  << ": " << (FnEnd-FnStart) << " bytes of text, "
                   << Relocations.size() << " relocations\n");
   Relocations.clear();
   return false;