Refactor the machine code emitter interface to pull the pointers for the current
authorChris Lattner <sabre@nondot.org>
Tue, 2 May 2006 18:27:26 +0000 (18:27 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 2 May 2006 18:27:26 +0000 (18:27 +0000)
code emission location into the base class, instead of being in the derived classes.

This change means that low-level methods like emitByte/emitWord now are no longer
virtual (yaay for speed), and we now have a framework to support growable code
segments.  This implements feature request #1 of PR469.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28059 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/MachineCodeEmitter.h
lib/CodeGen/ELFWriter.cpp
lib/CodeGen/MachineCodeEmitter.cpp [deleted file]
lib/ExecutionEngine/JIT/JITEmitter.cpp
lib/Target/Alpha/AlphaCodeEmitter.cpp
lib/Target/PowerPC/PPCCodeEmitter.cpp
lib/Target/X86/X86CodeEmitter.cpp

index 47ccef5317a04668f120b75ab3d901772d216927..72002ef897770fb97fc4a16d9975712bda7af390 100644 (file)
@@ -31,19 +31,50 @@ class Value;
 class GlobalValue;
 class Function;
 
+/// MachineCodeEmitter - This class defines two sorts of methods: those for
+/// emitting the actual bytes of machine code, and those for emitting auxillary
+/// structures, such as jump tables, relocations, etc.
+///
+/// Emission of machine code is complicated by the fact that we don't (in
+/// general) know the size of the machine code that we're about to emit before
+/// we emit it.  As such, we preallocate a certain amount of memory, and set the
+/// BufferBegin/BufferEnd pointers to the start and end of the buffer.  As we
+/// emit machine instructions, we advance the CurBufferPtr to indicate the
+/// location of the next byte to emit.  In the case of a buffer overflow (we
+/// need to emit more machine code than we have allocated space for), the
+/// CurBufferPtr will saturate to BufferEnd and ignore stores.  Once the entire
+/// function has been emitted, the overflow condition is checked, and if it has
+/// occurred, more memory is allocated, and we reemit the code into it.
+/// 
 class MachineCodeEmitter {
+protected:
+  /// BufferBegin/BufferEnd - Pointers to the start and end of the memory
+  /// allocated for this code buffer.
+  unsigned char *BufferBegin, *BufferEnd;
+  
+  /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting 
+  /// code.  This is guranteed to be in the range [BufferBegin,BufferEnd].  If
+  /// this pointer is at BufferEnd, it will never move due to code emission, and
+  /// all code emission requests will be ignored (this is the buffer overflow
+  /// condition).
+  unsigned char *CurBufferPtr;
 public:
   virtual ~MachineCodeEmitter() {}
 
   /// startFunction - This callback is invoked when the specified function is
-  /// about to be code generated.
+  /// about to be code generated.  This initializes the BufferBegin/End/Ptr
+  /// fields.
   ///
   virtual void startFunction(MachineFunction &F) {}
 
   /// finishFunction - This callback is invoked when the specified function has
-  /// finished code generation.
+  /// finished code generation.  If a buffer overflow has occurred, this method
+  /// returns true (the callee is required to try again), otherwise it returns
+  /// false.
   ///
-  virtual void finishFunction(MachineFunction &F) {}
+  virtual bool finishFunction(MachineFunction &F) {
+    return CurBufferPtr == BufferEnd;
+  }
 
   /// emitConstantPool - This callback is invoked to output the constant pool
   /// for the function.
@@ -63,7 +94,8 @@ public:
   /// startFunctionStub - This callback is invoked when the JIT needs the
   /// address of a function that has not been code generated yet.  The StubSize
   /// specifies the total size required by the stub.  Stubs are not allowed to
-  /// have constant pools, the can only use the other emit* methods.
+  /// have constant pools, the can only use the other emitByte*/emitWord*
+  /// methods.
   ///
   virtual void startFunctionStub(unsigned StubSize) {}
 
@@ -75,22 +107,36 @@ public:
   /// emitByte - This callback is invoked when a byte needs to be written to the
   /// output stream.
   ///
-  virtual void emitByte(unsigned char B) {}
+  void emitByte(unsigned char B) {
+    if (CurBufferPtr != BufferEnd)
+      *CurBufferPtr++ = B;
+  }
 
   /// emitWord - This callback is invoked when a word needs to be written to the
   /// output stream.
   ///
-  virtual void emitWord(unsigned W) = 0;
+  void emitWord(unsigned W) {
+    // FIXME: handle endian mismatches for .o file emission.
+    if (CurBufferPtr+4 <= BufferEnd) {
+      *(unsigned*)CurBufferPtr = W;
+      CurBufferPtr += 4;
+    } else {
+      CurBufferPtr = BufferEnd;
+    }
+  }
 
   /// getCurrentPCValue - This returns the address that the next emitted byte
   /// will be output to.
   ///
-  virtual uint64_t getCurrentPCValue() = 0;
-
+  virtual intptr_t getCurrentPCValue() const {
+    return (intptr_t)CurBufferPtr;
+  }
 
   /// getCurrentPCOffset - Return the offset from the start of the emitted
   /// buffer that we are currently writing to.
-  virtual uint64_t getCurrentPCOffset() = 0;
+  intptr_t getCurrentPCOffset() const {
+    return CurBufferPtr-BufferBegin;
+  }
 
   /// addRelocation - Whenever a relocatable address is needed, it should be
   /// noted with this interface.
@@ -108,12 +154,6 @@ public:
   
   // allocateGlobal - Allocate some space for a global variable.
   virtual unsigned char* allocateGlobal(unsigned size, unsigned alignment) = 0;
-
-  /// createFilePrinterEmitter - Return a dynamically allocated
-  /// machine code emitter, which prints binary code to a file.  This
-  /// can be used for debugging users of the MachineCodeEmitter interface.
-  ///
-  static MachineCodeEmitter *createFilePrinterEmitter(MachineCodeEmitter&);
 };
 
 } // End llvm namespace
index a802c1aa793ea5b80cdd0c66d16eda0adb13c3e4..c03b6272b561a5d1041d6739b408b569cfbdf190 100644 (file)
@@ -56,24 +56,12 @@ namespace llvm {
     ELFCodeEmitter(ELFWriter &ew) : EW(ew), OutBuffer(0) {}
 
     void startFunction(MachineFunction &F);
-    void finishFunction(MachineFunction &F);
+    bool finishFunction(MachineFunction &F);
 
     void emitConstantPool(MachineConstantPool *MCP) {
       if (MCP->isEmpty()) return;
       assert(0 && "unimp");
     }
-    virtual void emitByte(unsigned char B) {
-      OutBuffer->push_back(B);
-    }
-    virtual void emitWord(unsigned W) {
-      assert(0 && "ni");
-    }
-    virtual uint64_t getCurrentPCValue() {
-      return OutBuffer->size();
-    }
-    virtual uint64_t getCurrentPCOffset() {
-      return OutBuffer->size()-FnStart;
-    }
     void addRelocation(const MachineRelocation &MR) {
       assert(0 && "relo not handled yet!");
     }
@@ -113,6 +101,10 @@ void ELFCodeEmitter::startFunction(MachineFunction &F) {
                       ELFWriter::ELFSection::SHF_EXECINSTR |
                       ELFWriter::ELFSection::SHF_ALLOC);
   OutBuffer = &ES->SectionData;
+  std::cerr << "FIXME: This code needs to be updated for changes in the"
+            << " CodeEmitter interfaces.  In particular, this should set "
+            << "BufferBegin/BufferEnd/CurBufferPtr, not deal with OutBuffer!";
+  abort();
 
   // Upgrade the section alignment if required.
   if (ES->Align < Align) ES->Align = Align;
@@ -127,7 +119,7 @@ void ELFCodeEmitter::startFunction(MachineFunction &F) {
 
 /// finishFunction - This callback is invoked after the function is completely
 /// finished.
-void ELFCodeEmitter::finishFunction(MachineFunction &F) {
+bool ELFCodeEmitter::finishFunction(MachineFunction &F) {
   // We now know the size of the function, add a symbol to represent it.
   ELFWriter::ELFSym FnSym(F.getFunction());
 
@@ -157,6 +149,7 @@ void ELFCodeEmitter::finishFunction(MachineFunction &F) {
 
   // Finally, add it to the symtab.
   EW.SymbolTable.push_back(FnSym);
+  return false;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/MachineCodeEmitter.cpp b/lib/CodeGen/MachineCodeEmitter.cpp
deleted file mode 100644 (file)
index 301d9af..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-//===-- MachineCodeEmitter.cpp - Implement the MachineCodeEmitter itf -----===//
-//
-//                     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 implements the MachineCodeEmitter interface.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGen/MachineCodeEmitter.h"
-#include <fstream>
-#include <iostream>
-using namespace llvm;
-
-namespace {
-  class FilePrinterEmitter : public MachineCodeEmitter {
-    std::ofstream actual;
-    std::ostream &o;
-    MachineCodeEmitter &MCE;
-    unsigned counter;
-    unsigned values[4];
-
-  public:
-    FilePrinterEmitter(MachineCodeEmitter &M, std::ostream &os)
-      : o(os), MCE(M), counter(0) {
-      openActual();
-    }
-
-    ~FilePrinterEmitter() {
-      o << "\n";
-      actual.close();
-    }
-
-    void openActual() {
-      actual.open("lli.actual.obj");
-      if (!actual.good()) {
-        std::cerr << "Cannot open 'lli.actual.obj' for writing\n";
-        abort();
-      }
-    }
-
-    void startFunction(MachineFunction &F) {
-      // resolve any outstanding calls
-      MCE.startFunction(F);
-    }
-    void finishFunction(MachineFunction &F) {
-      MCE.finishFunction(F);
-    }
-
-    void emitConstantPool(MachineConstantPool *MCP) {
-      MCE.emitConstantPool(MCP);
-    }
-    void initJumpTableInfo(MachineJumpTableInfo *MJTI) {
-      MCE.initJumpTableInfo(MJTI);
-    }
-    void emitJumpTableInfo(MachineJumpTableInfo *MJTI,
-                           std::map<MachineBasicBlock*,uint64_t> &MBBM) {
-      MCE.emitJumpTableInfo(MJTI, MBBM);
-    }
-    
-    void startFunctionStub(unsigned StubSize) {
-      MCE.startFunctionStub(StubSize);
-    }
-
-    void *finishFunctionStub(const Function *F) {
-      return MCE.finishFunctionStub(F);
-    }
-
-    void emitByte(unsigned char B) {
-      MCE.emitByte(B);
-      actual << B; actual.flush();
-
-      values[counter] = (unsigned int) B;
-      if (++counter % 4 == 0 && counter != 0) {
-        o << std::hex;
-        for (unsigned i=0; i<4; ++i) {
-          if (values[i] < 16) o << "0";
-          o << values[i] << " ";
-        }
-
-        o << std::dec << "\t";
-        for (unsigned i=0; i<4; ++i) {
-          for (int j=7; j>=0; --j) {
-            o << ((values[i] >> j) & 1);
-          }
-          o << " ";
-        }
-
-        o << "\n";
-
-        unsigned instr = 0;
-        for (unsigned i=0; i<4; ++i)
-          instr |= values[i] << (i*8);
-
-        o << "--- * --- * --- * --- * ---\n";
-        counter %= 4;
-      }
-    }
-
-    void emitWord(unsigned W) {
-      MCE.emitWord(W);
-    }
-    uint64_t getConstantPoolEntryAddress(unsigned Num) {
-      return MCE.getConstantPoolEntryAddress(Num);
-    }
-    uint64_t getJumpTableEntryAddress(unsigned Num) {
-      return MCE.getJumpTableEntryAddress(Num);
-    }
-    virtual unsigned char* allocateGlobal(unsigned size, unsigned alignment)
-    { return MCE.allocateGlobal(size, alignment); }
-
-    uint64_t getCurrentPCValue() {
-      return MCE.getCurrentPCValue();
-    }
-    uint64_t getCurrentPCOffset() {
-      return MCE.getCurrentPCOffset();
-    }
-    void addRelocation(const MachineRelocation &MR) {
-      return MCE.addRelocation(MR);
-    }
-  };
-}
-
-MachineCodeEmitter *
-MachineCodeEmitter::createFilePrinterEmitter(MachineCodeEmitter &MCE) {
-  return new FilePrinterEmitter(MCE, std::cerr);
-}
index cbe8f7af5557eb486aacec69e4838b4ba7810a79..108b6b85833997e231456a8736c264d1ceda7c74 100644 (file)
@@ -413,13 +413,9 @@ namespace {
   class JITEmitter : public MachineCodeEmitter {
     JITMemoryManager MemMgr;
 
-    // CurBlock - The start of the current block of memory.  CurByte - The
-    // current byte being emitted to.
-    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;
+    // save BufferBegin/BufferEnd/CurBufferPtr here.
+    unsigned char *SavedBufferBegin, *SavedBufferEnd, *SavedCurBufferPtr;
 
     /// Relocations - These are the relocations that the function needs, as
     /// emitted.
@@ -449,22 +445,18 @@ public:
     }
 
     virtual void startFunction(MachineFunction &F);
-    virtual void finishFunction(MachineFunction &F);
+    virtual bool finishFunction(MachineFunction &F);
     virtual void emitConstantPool(MachineConstantPool *MCP);
     virtual void initJumpTableInfo(MachineJumpTableInfo *MJTI);
     virtual void emitJumpTableInfo(MachineJumpTableInfo *MJTI,
                                    std::map<MachineBasicBlock*,uint64_t> &MBBM);
     virtual void startFunctionStub(unsigned StubSize);
     virtual void* finishFunctionStub(const Function *F);
-    virtual void emitByte(unsigned char B);
-    virtual void emitWord(unsigned W);
 
     virtual void addRelocation(const MachineRelocation &MR) {
       Relocations.push_back(MR);
     }
 
-    virtual uint64_t getCurrentPCValue();
-    virtual uint64_t getCurrentPCOffset();
     virtual uint64_t getConstantPoolEntryAddress(unsigned Entry);
     virtual uint64_t getJumpTableEntryAddress(unsigned Entry);
     virtual unsigned char* allocateGlobal(unsigned size, unsigned alignment);
@@ -511,13 +503,16 @@ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference,
 }
 
 void JITEmitter::startFunction(MachineFunction &F) {
-  CurByte = CurBlock = MemMgr.startFunctionBody();
-  TheJIT->addGlobalMapping(F.getFunction(), CurBlock);
+  BufferBegin = CurBufferPtr = MemMgr.startFunctionBody();
+  TheJIT->updateGlobalMapping(F.getFunction(), BufferBegin);
+  
+  /// FIXME: implement out of space handling correctly!
+  BufferEnd = (unsigned char*)(intptr_t)~0ULL;
 }
 
-void JITEmitter::finishFunction(MachineFunction &F) {
-  MemMgr.endFunctionBody(CurByte);
-  NumBytes += CurByte-CurBlock;
+bool JITEmitter::finishFunction(MachineFunction &F) {
+  MemMgr.endFunctionBody(CurBufferPtr);
+  NumBytes += getCurrentPCOffset();
 
   if (!Relocations.empty()) {
     NumRelos += Relocations.size();
@@ -534,7 +529,7 @@ void JITEmitter::finishFunction(MachineFunction &F) {
           ResultPtr = getJITResolver(this).getExternalFunctionStub(ResultPtr);
       } else if (MR.isGlobalValue())
         ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
-                                       CurBlock+MR.getMachineCodeOffset(),
+                                       BufferBegin+MR.getMachineCodeOffset(),
                                        MR.doesntNeedFunctionStub());
       else //ConstantPoolIndex
         ResultPtr =
@@ -557,25 +552,26 @@ void JITEmitter::finishFunction(MachineFunction &F) {
       }
     }
 
-    TheJIT->getJITInfo().relocate(CurBlock, &Relocations[0],
+    TheJIT->getJITInfo().relocate(BufferBegin, &Relocations[0],
                                   Relocations.size(), MemMgr.getGOTBase());
   }
 
   //Update the GOT entry for F to point to the new code.
   if(MemMgr.isManagingGOT()) {
-    unsigned idx = getJITResolver(this).getGOTIndexForAddr((void*)CurBlock);
-    if (((void**)MemMgr.getGOTBase())[idx] != (void*)CurBlock) {
-      DEBUG(std::cerr << "GOT was out of date for " << (void*)CurBlock
+    unsigned idx = getJITResolver(this).getGOTIndexForAddr((void*)BufferBegin);
+    if (((void**)MemMgr.getGOTBase())[idx] != (void*)BufferBegin) {
+      DEBUG(std::cerr << "GOT was out of date for " << (void*)BufferBegin
             << " pointing at " << ((void**)MemMgr.getGOTBase())[idx] << "\n");
-      ((void**)MemMgr.getGOTBase())[idx] = (void*)CurBlock;
+      ((void**)MemMgr.getGOTBase())[idx] = (void*)BufferBegin;
     }
   }
 
-  DEBUG(std::cerr << "JIT: Finished CodeGen of [" << (void*)CurBlock
+  DEBUG(std::cerr << "JIT: Finished CodeGen of [" << (void*)BufferBegin
                   << "] Function: " << F.getFunction()->getName()
-                  << ": " << CurByte-CurBlock << " bytes of text, "
+                  << ": " << getCurrentPCOffset() << " bytes of text, "
                   << Relocations.size() << " relocations\n");
   Relocations.clear();
+  return false;
 }
 
 void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
@@ -648,26 +644,20 @@ void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI,
 }
 
 void JITEmitter::startFunctionStub(unsigned StubSize) {
-  SavedCurBlock = CurBlock;  SavedCurByte = CurByte;
-  CurByte = CurBlock = MemMgr.allocateStub(StubSize);
+  SavedBufferBegin = BufferBegin;
+  SavedBufferEnd = BufferEnd;
+  SavedCurBufferPtr = CurBufferPtr;
+  
+  BufferBegin = CurBufferPtr = MemMgr.allocateStub(StubSize);
+  BufferEnd = BufferBegin+StubSize+1;
 }
 
 void *JITEmitter::finishFunctionStub(const Function *F) {
-  NumBytes += CurByte-CurBlock;
-  std::swap(CurBlock, SavedCurBlock);
-  CurByte = SavedCurByte;
-  return SavedCurBlock;
-}
-
-void JITEmitter::emitByte(unsigned char B) {
-  *CurByte++ = B;   // Write the byte to memory
-}
-
-void JITEmitter::emitWord(unsigned W) {
-  // This won't work if the endianness of the host and target don't agree!  (For
-  // a JIT this can't happen though.  :)
-  *(unsigned*)CurByte = W;
-  CurByte += sizeof(unsigned);
+  NumBytes += getCurrentPCOffset();
+  std::swap(SavedBufferBegin, BufferBegin);
+  BufferEnd = SavedBufferEnd;
+  CurBufferPtr = SavedCurBufferPtr;
+  return SavedBufferBegin;
 }
 
 // getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry
@@ -702,17 +692,6 @@ unsigned char* JITEmitter::allocateGlobal(unsigned size, unsigned alignment)
   return MemMgr.allocateGlobal(size, alignment);
 }
 
-// getCurrentPCValue - This returns the address that the next emitted byte
-// will be output to.
-//
-uint64_t JITEmitter::getCurrentPCValue() {
-  return (intptr_t)CurByte;
-}
-
-uint64_t JITEmitter::getCurrentPCOffset() {
-  return (intptr_t)CurByte-(intptr_t)CurBlock;
-}
-
 // getPointerToNamedFunction - This function is used as a global wrapper to
 // JIT::getPointerToNamedFunction for the purpose of resolving symbols when
 // bugpoint is debugging the JIT. In that scenario, we are loading an .so and
index f5d517fadd49d634280ca828329b39184c8b40b9..dfb7820cae859027f0ce1f3056f900ec7973852d 100644 (file)
@@ -80,11 +80,15 @@ FunctionPass *llvm::createAlphaCodeEmitterPass(MachineCodeEmitter &MCE) {
 bool AlphaCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
   II = ((AlphaTargetMachine&)MF.getTarget()).getInstrInfo();
 
-  MCE.startFunction(MF);
-  MCE.emitConstantPool(MF.getConstantPool());
-  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
-    emitBasicBlock(*I);
-  MCE.finishFunction(MF);
+  do {
+    BBRefs.clear();
+    BasicBlockAddrs.clear();
+    
+    MCE.startFunction(MF);
+    MCE.emitConstantPool(MF.getConstantPool());
+    for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
+      emitBasicBlock(*I);
+  } while (MCE.finishFunction(MF));
 
   // Resolve all forward branches now...
   for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
index c7f2acbd77ce5c471e49a273421a8ed81508000a..1b305f4b243ccaddcf9606636c25c0739e429f6d 100644 (file)
@@ -89,13 +89,17 @@ bool PPCCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
   assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
           MF.getTarget().getRelocationModel() != Reloc::Static) &&
          "JIT relocation model must be set to static or default!");
-  MCE.startFunction(MF);
-  MCE.emitConstantPool(MF.getConstantPool());
-  MCE.initJumpTableInfo(MF.getJumpTableInfo());
-  for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
-    emitBasicBlock(*BB);
-  MCE.emitJumpTableInfo(MF.getJumpTableInfo(), BBLocations);
-  MCE.finishFunction(MF);
+  do {
+    BBRefs.clear();
+    BBLocations.clear();
+
+    MCE.startFunction(MF);
+    MCE.emitConstantPool(MF.getConstantPool());
+    MCE.initJumpTableInfo(MF.getJumpTableInfo());
+    for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
+      emitBasicBlock(*BB);
+    MCE.emitJumpTableInfo(MF.getJumpTableInfo(), BBLocations);
+  } while (MCE.finishFunction(MF));
 
   // Resolve branches to BasicBlocks for the entire function
   for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
index 75bc6ce1e33012aed7f4274df14879bd606ccbae..a278fd548b5eb1075daa8742d9330a8274ad1850 100644 (file)
@@ -81,13 +81,17 @@ bool Emitter::runOnMachineFunction(MachineFunction &MF) {
          "JIT relocation model must be set to static or default!");
   II = ((X86TargetMachine&)MF.getTarget()).getInstrInfo();
 
-  MCE.startFunction(MF);
-  MCE.emitConstantPool(MF.getConstantPool());
-  MCE.initJumpTableInfo(MF.getJumpTableInfo());
-  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
-    emitBasicBlock(*I);
-  MCE.emitJumpTableInfo(MF.getJumpTableInfo(), BasicBlockAddrs);
-  MCE.finishFunction(MF);
+  do {
+    BBRefs.clear();
+    BasicBlockAddrs.clear();
+
+    MCE.startFunction(MF);
+    MCE.emitConstantPool(MF.getConstantPool());
+    MCE.initJumpTableInfo(MF.getJumpTableInfo());
+    for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
+      emitBasicBlock(*I);
+    MCE.emitJumpTableInfo(MF.getJumpTableInfo(), BasicBlockAddrs);
+  } while (MCE.finishFunction(MF));
 
   // Resolve all forward branches now.
   for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {