[LLVMdev] Being able to know the jitted code-size before emitting

Tanya Lattner tonic at nondot.org
Sun Mar 30 15:35:52 PDT 2008


On Mar 30, 2008, at 12:05 PM, Nicolas Geoffray wrote:

> Hi everyone,
>
> vmkit requires to know the size of a jitted method before emitting  
> the method. This allows to allocate the correct size for the method.  
> The attached patch creates this functionality when the flag  
> SizedMemoryCode is on.
>
> In order to implement this functionality, i had to virtualize some  
> MachineCodeEmitter functions.
>
> Is it OK to commit the patch?
>

A couple style comments:

- The header for SizeEmitter.h is the old style. Please remove the  
part about "was developed by".  You can see other files for the  
correct format. I think SizeEmitter.cpp is missing the header totally.
- SizeEmitter.h/SizeEmitter.cpp is lacking comments. Please add  
doxygen style comments for all functions and member variables.


Thanks,
Tanya


> Thanks,
> Nicolas
> Index: include/llvm/Target/TargetOptions.h
> ===================================================================
> --- include/llvm/Target/TargetOptions.h (revision 48944)
> +++ include/llvm/Target/TargetOptions.h (working copy)
> @@ -74,6 +74,10 @@
>   /// be emitted.
>   extern bool ExceptionHandling;
>
> +  /// SizedMemoryCode - This flags indicates that memory for code  
> is allocated by
> +  /// an external allocator which requires the size to allocate
> +  extern bool SizedMemoryCode;
> +
>   /// PerformTailCallOpt - This flag is enabled when -tailcallopt is  
> specified
>   /// on the commandline. When the flag is on, the target will  
> perform tail call
>   /// optimization (pop the caller's stack) providing it supports it.
> Index: include/llvm/CodeGen/SizeEmitter.h
> ===================================================================
> --- include/llvm/CodeGen/SizeEmitter.h	(revision 0)
> +++ include/llvm/CodeGen/SizeEmitter.h	(revision 0)
> @@ -0,0 +1,116 @@
> +//===-- llvm/CodeGen/MachineCodeEmitter.h - Code emission -------*-  
> C++ -*-===//
> +//
> +//                     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 defines an abstract interface that is used by the  
> machine code
> +// emission framework to output the code.  This allows machine code  
> emission to
> +// be separated from concerns such as resolution of call targets,  
> and where the
> +// machine code will be written (memory or disk, f.e.).
> +//
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +
> +#ifndef LLVM_CODEGEN_SIZEEMITTER_H
> +#define LLVM_CODEGEN_SIZEEMITTER_H
> +
> +#include "llvm/CodeGen/MachineCodeEmitter.h"
> +#include "llvm/CodeGen/MachineFunction.h"
> +
> +namespace llvm {
> +  /// SizeEmitter - The JIT implementation of the  
> MachineCodeEmitter, which is
> +  /// used to output functions to memory for execution.
> +class SizeEmitter : public MachineCodeEmitter {
> +  MachineFunction * Fn;
> +  void* ConstantPoolBase;
> +  void* JumpTableBase;
> +  MachineConstantPool *ConstantPool;
> +  MachineJumpTableInfo *JumpTable;
> +  std::vector<intptr_t> LabelLocations;
> +  MachineCodeEmitter* MCE;
> +
> +public:
> +  SizeEmitter(MachineCodeEmitter* mce) {
> +    CurBufferPtr = 0;
> +    BufferBegin = 0;
> +    BufferEnd = (unsigned char*)-1;
> +    MCE = mce;
> +  }
> +
> +  SizeEmitter(std::vector<intptr_t> locations) {
> +    LabelLocations = locations;
> +    CurBufferPtr = 0;
> +    BufferBegin = 0;
> +    BufferEnd = (unsigned char*)-1;
> +  }
> +
> +  void initConstantPool(MachineConstantPool *MCP);
> +
> +  void initJumpTableInfo(MachineJumpTableInfo *MJTI);
> +
> +
> +  virtual void startFunction(MachineFunction &F) {
> +    CurBufferPtr = 0;
> +    Fn = &F;
> +
> +    // Ensure the constant pool/jump table info is at least 4-byte  
> aligned.
> +    emitAlignment(16);
> +
> +    initConstantPool(F.getConstantPool());
> +    initJumpTableInfo(F.getJumpTableInfo());
> +
> +    ConstantPoolBase  = (void*)(((uintptr_t) ConstantPoolBase) +  
> CurBufferPtr);
> +    JumpTableBase     = (void*)(((uintptr_t) JumpTableBase) +  
> CurBufferPtr);
> +  }
> +
> +  virtual bool finishFunction(MachineFunction &F) {
> +    MCE->setCurrentPtr(CurBufferPtr);
> +    return false;
> +  }
> +  virtual void startFunctionStub(unsigned StubSize, unsigned  
> Alignment) {}
> +  virtual void *finishFunctionStub(const Function *F) { return 0; }
> +  virtual void addRelocation(const llvm::MachineRelocation&) { }
> +  virtual void emitByte(unsigned char B) {
> +    CurBufferPtr++;
> +  }
> +  virtual void emitWordLE(unsigned W) {
> +    CurBufferPtr+=4;
> +  }
> +  virtual void emitWordBE(unsigned W) {
> +    CurBufferPtr+=4;
> +  }
> +  virtual void emitInt32(int Value) {
> +    CurBufferPtr += 4;
> +  }
> +  virtual void emitInt64(uint64_t Value) {
> +    CurBufferPtr += 8;
> +  }
> +  virtual void emitAt(uintptr_t *Addr, uintptr_t Value) {
> +  }
> +
> +
> +
> +  virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) {}
> +  virtual intptr_t getConstantPoolEntryAddress(unsigned  
> ConstantNum) const;
> +
> +  virtual intptr_t getJumpTableEntryAddress(unsigned Index) const;
> +
> +  virtual intptr_t getMachineBasicBlockAddress(MachineBasicBlock  
> *MBB) const {
> +    assert(0 && "Should not be in getMachineBasicBlockAddress of  
> SizeEmitter");
> +  }
> +
> +  virtual void emitLabel(uint64_t) {}
> +  virtual intptr_t getLabelAddress(uint64_t LabelID) const {
> +    assert(LabelLocations.size() > (unsigned)LabelID &&
> +             LabelLocations[LabelID] && "Label not emitted!");
> +      return LabelLocations[LabelID];
> +  }
> +  virtual void setModuleInfo(llvm::MachineModuleInfo*) {}
> +};
> +
> +} // end llvm namespace
> +
> +#endif
> Index: include/llvm/CodeGen/MachineCodeEmitter.h
> ===================================================================
> --- include/llvm/CodeGen/MachineCodeEmitter.h	(revision 48143)
> +++ include/llvm/CodeGen/MachineCodeEmitter.h	(working copy)
> @@ -18,6 +18,7 @@
> #define LLVM_CODEGEN_MACHINECODEEMITTER_H
>
> #include "llvm/Support/DataTypes.h"
> +#include <string>
> #include <vector>
>
> namespace llvm {
> @@ -92,7 +93,7 @@
>   /// emitByte - This callback is invoked when a byte needs to be  
> written to the
>   /// output stream.
>   ///
> -  void emitByte(unsigned char B) {
> +  virtual void emitByte(unsigned char B) {
>     if (CurBufferPtr != BufferEnd)
>       *CurBufferPtr++ = B;
>   }
> @@ -100,7 +101,7 @@
>   /// emitWordLE - This callback is invoked when a 32-bit word needs  
> to be
>   /// written to the output stream in little-endian format.
>   ///
> -  void emitWordLE(unsigned W) {
> +  virtual void emitWordLE(unsigned W) {
>     if (CurBufferPtr+4 <= BufferEnd) {
>       *CurBufferPtr++ = (unsigned char)(W >>  0);
>       *CurBufferPtr++ = (unsigned char)(W >>  8);
> @@ -114,7 +115,7 @@
>   /// emitWordBE - This callback is invoked when a 32-bit word needs  
> to be
>   /// written to the output stream in big-endian format.
>   ///
> -  void emitWordBE(unsigned W) {
> +  virtual void emitWordBE(unsigned W) {
>     if (CurBufferPtr+4 <= BufferEnd) {
>       *CurBufferPtr++ = (unsigned char)(W >> 24);
>       *CurBufferPtr++ = (unsigned char)(W >> 16);
> @@ -175,7 +176,7 @@
>   }
>
>   /// emitInt32 - Emit a int32 directive.
> -  void emitInt32(int Value) {
> +  virtual void emitInt32(int Value) {
>     if (CurBufferPtr+4 <= BufferEnd) {
>       *((uint32_t*)CurBufferPtr) = Value;
>       CurBufferPtr += 4;
> @@ -185,7 +186,7 @@
>   }
>
>   /// emitInt64 - Emit a int64 directive.
> -  void emitInt64(uint64_t Value) {
> +  virtual void emitInt64(uint64_t Value) {
>     if (CurBufferPtr+8 <= BufferEnd) {
>       *((uint64_t*)CurBufferPtr) = Value;
>       CurBufferPtr += 8;
> @@ -195,7 +196,7 @@
>   }
>
>   /// emitAt - Emit Value in Addr
> -  void emitAt(uintptr_t *Addr, uintptr_t Value) {
> +  virtual void emitAt(uintptr_t *Addr, uintptr_t Value) {
>     if (Addr >= (uintptr_t*)BufferBegin && Addr <  
> (uintptr_t*)BufferEnd)
>       (*Addr) = Value;
>   }
> @@ -270,6 +271,11 @@
>   /// Specifies the MachineModuleInfo object. This is used for  
> exception handling
>   /// purposes.
>   virtual void setModuleInfo(MachineModuleInfo* Info) = 0;
> +
> +  void setCurrentPtr(unsigned char* Ptr) {
> +    CurBufferPtr = Ptr;
> +  }
> +
> };
>
> } // End llvm namespace
> Index: lib/CodeGen/LLVMTargetMachine.cpp
> ===================================================================
> --- lib/CodeGen/LLVMTargetMachine.cpp	(revision 48143)
> +++ lib/CodeGen/LLVMTargetMachine.cpp	(working copy)
> @@ -17,6 +17,7 @@
> #include "llvm/Assembly/PrintModulePass.h"
> #include "llvm/Analysis/LoopPass.h"
> #include "llvm/CodeGen/Passes.h"
> +#include "llvm/CodeGen/SizeEmitter.h"
> #include "llvm/CodeGen/Collector.h"
> #include "llvm/Target/TargetOptions.h"
> #include "llvm/Transforms/Scalar.h"
> @@ -257,7 +258,13 @@
>
>   if (addPreEmitPass(PM, Fast) && PrintMachineCode)
>     PM.add(createMachineFunctionPrinterPass(cerr));
> +
> +  if (SizedMemoryCode) {
> +    SizeEmitter * SE = new SizeEmitter(&MCE);
> +    addSimpleCodeEmitter(PM, Fast, false, *SE);
> +  }
>
> +
>   addCodeEmitter(PM, Fast, PrintEmittedAsm, MCE);
>
>   PM.add(createCollectorMetadataDeleter());
> Index: lib/CodeGen/SizeEmitter.cpp
> ===================================================================
> --- lib/CodeGen/SizeEmitter.cpp	(revision 0)
> +++ lib/CodeGen/SizeEmitter.cpp	(revision 0)
> @@ -0,0 +1,77 @@
> +#include "llvm/CodeGen/SizeEmitter.h"
> +#include "llvm/Constant.h"
> +#include "llvm/Constants.h"
> +#include "llvm/DerivedTypes.h"
> +#include "llvm/Module.h"
> +#include "llvm/Type.h"
> +#include "llvm/CodeGen/MachineCodeEmitter.h"
> +#include "llvm/CodeGen/MachineFunction.h"
> +#include "llvm/CodeGen/MachineConstantPool.h"
> +#include "llvm/CodeGen/MachineJumpTableInfo.h"
> +#include "llvm/CodeGen/MachineRelocation.h"
> +#include "llvm/ExecutionEngine/GenericValue.h"
> +#include "llvm/Target/TargetData.h"
> +#include "llvm/Target/TargetJITInfo.h"
> +#include "llvm/Target/TargetMachine.h"
> +#include "llvm/Target/TargetOptions.h"
> +#include "llvm/Support/Debug.h"
> +#include "llvm/Support/MutexGuard.h"
> +#include "llvm/System/Disassembler.h"
> +#include "llvm/ADT/Statistic.h"
> +#include "llvm/System/Memory.h"
> +#include <algorithm>
> +using namespace llvm;
> +
> +
> +void SizeEmitter::initConstantPool(MachineConstantPool *MCP) {
> +  const std::vector<MachineConstantPoolEntry> &Constants = MCP- 
> >getConstants();
> +  if (Constants.empty()) return;
> +
> +  MachineConstantPoolEntry CPE = Constants.back();
> +  unsigned Size = CPE.Offset;
> +  const Type *Ty = CPE.isMachineConstantPoolEntry()
> +    ? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType();
> +  Size += Fn->getTarget().getTargetData()->getABITypeSize(Ty);
> +  ConstantPoolBase = allocateSpace(Size, 1 << MCP- 
> >getConstantPoolAlignment());
> +  ConstantPool = MCP;
> +}
> +
> +void SizeEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) {
> +  const std::vector<MachineJumpTableEntry> &JT = MJTI- 
> >getJumpTables();
> +  if (JT.empty()) return;
> +
> +  unsigned NumEntries = 0;
> +  for (unsigned i = 0, e = JT.size(); i != e; ++i)
> +    NumEntries += JT[i].MBBs.size();
> +
> +  unsigned EntrySize = MJTI->getEntrySize();
> +
> +  // Just allocate space for all the jump tables now.  We will fix  
> up the actual
> +  // MBB entries in the tables after we emit the code for each  
> block, since then
> +  // we will know the final locations of the MBBs in memory.
> +  JumpTable = MJTI;
> +  JumpTableBase = allocateSpace(NumEntries * EntrySize, MJTI- 
> >getAlignment());
> +}
> +
> +intptr_t SizeEmitter::getConstantPoolEntryAddress(unsigned  
> ConstantNum) const {
> +  assert(ConstantNum < ConstantPool->getConstants().size() &&
> +         "Invalid ConstantPoolIndex!");
> +  return (intptr_t)ConstantPoolBase +
> +         ConstantPool->getConstants()[ConstantNum].Offset;
> +}
> +
> +intptr_t SizeEmitter::getJumpTableEntryAddress(unsigned Index)  
> const {
> +  const std::vector<MachineJumpTableEntry> &JT = JumpTable- 
> >getJumpTables();
> +  assert(Index < JT.size() && "Invalid jump table index!");
> +
> +  unsigned Offset = 0;
> +  unsigned EntrySize = JumpTable->getEntrySize();
> +
> +  for (unsigned i = 0; i < Index; ++i)
> +    Offset += JT[i].MBBs.size();
> +
> +   Offset *= EntrySize;
> +
> +  return (intptr_t)((char *)JumpTableBase + Offset);
> +}
> +
> Index: lib/Target/TargetMachine.cpp
> ===================================================================
> --- lib/Target/TargetMachine.cpp	(revision 48143)
> +++ lib/Target/TargetMachine.cpp	(working copy)
> @@ -31,6 +31,7 @@
>   bool UseSoftFloat;
>   bool NoZerosInBSS;
>   bool ExceptionHandling;
> +  bool SizedMemoryCode;
>   Reloc::Model RelocationModel;
>   CodeModel::Model CMModel;
>   bool PerformTailCallOpt;
> Index: lib/ExecutionEngine/JIT/JITEmitter.cpp
> ===================================================================
> --- lib/ExecutionEngine/JIT/JITEmitter.cpp	(revision 48143)
> +++ lib/ExecutionEngine/JIT/JITEmitter.cpp	(working copy)
> @@ -18,12 +18,14 @@
> #include "llvm/Constant.h"
> #include "llvm/Module.h"
> #include "llvm/Type.h"
> +#include "llvm/ADT/DenseMap.h"
> #include "llvm/CodeGen/MachineCodeEmitter.h"
> #include "llvm/CodeGen/MachineFunction.h"
> #include "llvm/CodeGen/MachineConstantPool.h"
> #include "llvm/CodeGen/MachineJumpTableInfo.h"
> #include "llvm/CodeGen/MachineModuleInfo.h"
> #include "llvm/CodeGen/MachineRelocation.h"
> +#include "llvm/CodeGen/SizeEmitter.h"
> #include "llvm/ExecutionEngine/JITMemoryManager.h"
> #include "llvm/Target/TargetData.h"
> #include "llvm/Target/TargetJITInfo.h"
> @@ -370,6 +376,7 @@
>     virtual void startFunction(MachineFunction &F);
>     virtual bool finishFunction(MachineFunction &F);
>
> +    void initConstantPool(MachineConstantPool *MCP);
>     void emitConstantPool(MachineConstantPool *MCP);
>     void initJumpTableInfo(MachineJumpTableInfo *MJTI);
>     void emitJumpTableInfo(MachineJumpTableInfo *MJTI);
> @@ -469,19 +476,47 @@
>
>
> void JITEmitter::startFunction(MachineFunction &F) {
> -  uintptr_t ActualSize;
> -  BufferBegin = CurBufferPtr = MemMgr- 
> >startFunctionBody(F.getFunction(),
> -                                                         ActualSize);
> -  BufferEnd = BufferBegin+ActualSize;
> +  MMI->BeginFunction(&F);
>
> -  // Ensure the constant pool/jump table info is at least 4-byte  
> aligned.
> -  emitAlignment(16);
> +  if (SizedMemoryCode) {
> +    BufferBegin = CurBufferPtr;
> +    BufferEnd = (unsigned char*) 0xffffffff;
> +
> +    // Ensure the constant pool/jump table info is at least 4-byte  
> aligned.
> +    emitAlignment(16);
>
> -  emitConstantPool(F.getConstantPool());
> -  initJumpTableInfo(F.getJumpTableInfo());
> +    initConstantPool(F.getConstantPool());
> +    initJumpTableInfo(F.getJumpTableInfo());
> +
> +
> +    uintptr_t ActualSize = (uintptr_t)CurBufferPtr;
> +    CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
> +                                             ActualSize);
> +
> +    ConstantPoolBase  = (void*)(((unsigned) ConstantPoolBase) +  
> CurBufferPtr);
> +    JumpTableBase     = (void*)(((unsigned) JumpTableBase) +  
> CurBufferPtr);
>
> -  // About to start emitting the machine code for the function.
> -  emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
> +    emitConstantPool(F.getConstantPool());
> +
> +  } else {
> +    uintptr_t ActualSize;
> +    BufferBegin = CurBufferPtr = MemMgr- 
> >startFunctionBody(F.getFunction(),
> +                                                            
> ActualSize);
> +    BufferEnd = BufferBegin+ActualSize;
> +
> +    // Ensure the constant pool/jump table info is at least 4-byte  
> aligned.
> +    emitAlignment(16);
> +
> +    initConstantPool(F.getConstantPool());
> +    emitConstantPool(F.getConstantPool());
> +    initJumpTableInfo(F.getJumpTableInfo());
> +
> +    // About to start emitting the machine code for the function.
> +    emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
> +
> +  }
> +
> +
>   TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr);
>
>   MBBLocations.clear();
> @@ -579,12 +614,18 @@
>     DOUT << "Disassembled code:\n"
>          << sys::disassembleBuffer(FnStart, FnEnd-FnStart,  
> (uintptr_t)FnStart);
> #endif
> +
>   if (ExceptionHandling) {
>     uintptr_t ActualSize;
> +    if (SizedMemoryCode) {
> +      SizeEmitter sz(LabelLocations);
> +      DE->EmitDwarfTable(F, sz, FnStart, FnEnd);
> +      ActualSize = sz.getCurrentPCValue();
> +    }
>     SavedBufferBegin = BufferBegin;
>     SavedBufferEnd = BufferEnd;
>     SavedCurBufferPtr = CurBufferPtr;
> -
> +
>     BufferBegin = CurBufferPtr = MemMgr- 
> >startExceptionTable(F.getFunction(),
>                                                               
> ActualSize);
>     BufferEnd = BufferBegin+ActualSize;
> @@ -598,11 +639,10 @@
>     TheJIT->RegisterTable(FrameRegister);
>   }
>   MMI->EndFunction();
> -
>   return false;
> }
>
> -void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
> +void JITEmitter::initConstantPool(MachineConstantPool *MCP) {
>   const std::vector<MachineConstantPoolEntry> &Constants = MCP- 
> >getConstants();
>   if (Constants.empty()) return;
>
> @@ -611,12 +651,15 @@
>   const Type *Ty = CPE.isMachineConstantPoolEntry()
>     ? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType();
>   Size += TheJIT->getTargetData()->getABITypeSize(Ty);
> -
> +
>   ConstantPoolBase = allocateSpace(Size, 1 << MCP- 
> >getConstantPoolAlignment());
>   ConstantPool = MCP;
> +}
>
> +void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
>   if (ConstantPoolBase == 0) return;  // Buffer overflow.
>
> +  const std::vector<MachineConstantPoolEntry> &Constants = MCP- 
> >getConstants();
>   // Initialize the memory for all of the constant pool entries.
>   for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
>     void *CAddr = (char*)ConstantPoolBase+Constants[i].Offset;
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev




More information about the llvm-dev mailing list