Add support for function stubs, which allow calling functions which need to
have an address available, but have not yet been code generated.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6059 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index 69e2453..f6f6b30 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -19,8 +19,11 @@
   class Emitter : public MachineCodeEmitter {
     VM &TheVM;
 
-    unsigned char *CurBlock;
-    unsigned char *CurByte;
+    unsigned char *CurBlock, *CurByte;
+
+    // When outputting a function stub in the context of some other function, we
+    // save CurBlock and CurByte here.
+    unsigned char *SavedCurBlock, *SavedCurByte;
     
     std::vector<std::pair<BasicBlock*, unsigned *> > BBRefs;
     std::map<BasicBlock*, unsigned> BBLocations;
@@ -32,6 +35,8 @@
     virtual void finishFunction(MachineFunction &F);
     virtual void emitConstantPool(MachineConstantPool *MCP);
     virtual void startBasicBlock(MachineBasicBlock &BB);
+    virtual void startFunctionStub(const Function &F, unsigned StubSize);
+    virtual void* finishFunctionStub(const Function &F);
     virtual void emitByte(unsigned char B);
     virtual void emitPCRelativeDisp(Value *V);
     virtual void emitGlobalAddress(GlobalValue *V, bool isPCRelative);
@@ -52,14 +57,16 @@
 #include <unistd.h>
 #include <sys/mman.h>
 
-static void *getMemory() {
-  return mmap(0, 4096*8, PROT_READ|PROT_WRITE|PROT_EXEC,
+// FIXME: This should be rewritten to support a real memory manager for
+// executable memory pages!
+static void *getMemory(unsigned NumPages) {
+  return mmap(0, 4096*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
               MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
 }
 
 
 void Emitter::startFunction(MachineFunction &F) {
-  CurBlock = (unsigned char *)getMemory();
+  CurBlock = (unsigned char *)getMemory(8);
   CurByte = CurBlock;  // Start writing at the beginning of the fn.
   TheVM.addGlobalMapping(F.getFunction(), CurBlock);
 }
@@ -100,6 +107,24 @@
 }
 
 
+void Emitter::startFunctionStub(const Function &F, unsigned StubSize) {
+  SavedCurBlock = CurBlock;  SavedCurByte = CurByte;
+  // FIXME: this is a huge waste of memory.
+  CurBlock = (unsigned char *)getMemory((StubSize+4095)/4096);
+  CurByte = CurBlock;  // Start writing at the beginning of the fn.
+}
+
+void *Emitter::finishFunctionStub(const Function &F) {
+  NumBytes += CurByte-CurBlock;
+  DEBUG(std::cerr << "Finished CodeGen of [0x" << std::hex
+                  << (unsigned)(intptr_t)CurBlock
+                  << std::dec << "] Function stub for: " << F.getName()
+                  << ": " << CurByte-CurBlock << " bytes of text\n");
+  std::swap(CurBlock, SavedCurBlock);
+  CurByte = SavedCurByte;
+  return SavedCurBlock;
+}
+
 void Emitter::emitByte(unsigned char B) {
   *CurByte++ = B;   // Write the byte to memory
 }