[LLVMdev] Being able to know the jitted code-size before emitting
Nicolas Geoffray
nicolas.geoffray at lip6.fr
Tue Apr 1 00:50:57 PDT 2008
Hi Evan,
Evan Cheng wrote:
> 1) How are you computing size of the method being
> jitted?
I add a new pass with addSimpleCodeEmitter, with the emitter being a
SizeEmitter. Since the target calls the emitter with functions such as
writeByte, writeWord, etc.... the SizeEmitter class implements these
function by incrementing a counter.
At the end of the pass, the code size of the function is known.
> 2) Why not simply add the functionality of allocating emission
> buffer of specific size to MachineCodeEmitter instead?
>
I don't understand. The MachineCodeEmitter class writes directly to a
buffer which is remalloc'ed if necessary. I want this buffer to be
pre-allocated and of the correct size. Hence I need a pass that runs
before emitting code.
Nicolas
> Thanks,
>
> Evan
>
> 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?
>>
>> 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
>>
>
> _______________________________________________
> 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