summaryrefslogtreecommitdiffstats
path: root/lib/ExecutionEngine/JIT/JITEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ExecutionEngine/JIT/JITEmitter.cpp')
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp292
1 files changed, 195 insertions, 97 deletions
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index 8fe7ab8..eacd9f9 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -14,7 +14,9 @@
#define DEBUG_TYPE "jit"
#include "JIT.h"
+#include "JITDebugRegisterer.h"
#include "JITDwarfEmitter.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
@@ -33,8 +35,10 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/ValueHandle.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Disassembler.h"
#include "llvm/System/Memory.h"
#include "llvm/Target/TargetInstrInfo.h"
@@ -49,6 +53,7 @@ using namespace llvm;
STATISTIC(NumBytes, "Number of bytes of machine code compiled");
STATISTIC(NumRelos, "Number of relocations applied");
+STATISTIC(NumRetries, "Number of retries with more memory");
static JIT *TheJIT = 0;
@@ -59,7 +64,7 @@ namespace {
class JITResolverState {
public:
typedef std::map<AssertingVH<Function>, void*> FunctionToStubMapTy;
- typedef std::map<void*, Function*> StubToFunctionMapTy;
+ typedef std::map<void*, AssertingVH<Function> > StubToFunctionMapTy;
typedef std::map<AssertingVH<GlobalValue>, void*> GlobalToIndirectSymMapTy;
private:
/// FunctionToStubMap - Keep track of the stub created for a particular
@@ -193,9 +198,9 @@ void *JITResolver::getFunctionStub(Function *F) {
// Call the lazy resolver function unless we are JIT'ing non-lazily, in which
// case we must resolve the symbol now.
- void *Actual = TheJIT->isLazyCompilationDisabled()
+ void *Actual = TheJIT->isLazyCompilationDisabled()
? (void *)0 : (void *)(intptr_t)LazyResolverFn;
-
+
// If this is an external declaration, attempt to resolve the address now
// to place in the stub.
if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode()) {
@@ -220,20 +225,20 @@ void *JITResolver::getFunctionStub(Function *F) {
TheJIT->updateGlobalMapping(F, Stub);
}
- DOUT << "JIT: Stub emitted at [" << Stub << "] for function '"
- << F->getName() << "'\n";
+ DEBUG(errs() << "JIT: Stub emitted at [" << Stub << "] for function '"
+ << F->getName() << "'\n");
// Finally, keep track of the stub-to-Function mapping so that the
// JITCompilerFn knows which function to compile!
state.getStubToFunctionMap(locked)[Stub] = F;
-
+
// If we are JIT'ing non-lazily but need to call a function that does not
// exist yet, add it to the JIT's work list so that we can fill in the stub
// address later.
if (!Actual && TheJIT->isLazyCompilationDisabled())
if (!F->isDeclaration() || F->hasNotBeenReadFromBitcode())
TheJIT->addPendingFunction(F);
-
+
return Stub;
}
@@ -250,8 +255,8 @@ void *JITResolver::getGlobalValueIndirectSym(GlobalValue *GV, void *GVAddress) {
IndirectSym = TheJIT->getJITInfo().emitGlobalValueIndirectSym(GV, GVAddress,
*TheJIT->getCodeEmitter());
- DOUT << "JIT: Indirect symbol emitted at [" << IndirectSym << "] for GV '"
- << GV->getName() << "'\n";
+ DEBUG(errs() << "JIT: Indirect symbol emitted at [" << IndirectSym
+ << "] for GV '" << GV->getName() << "'\n");
return IndirectSym;
}
@@ -266,8 +271,8 @@ void *JITResolver::getExternalFunctionStub(void *FnAddr) {
Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr,
*TheJIT->getCodeEmitter());
- DOUT << "JIT: Stub emitted at [" << Stub
- << "] for external function at '" << FnAddr << "'\n";
+ DEBUG(errs() << "JIT: Stub emitted at [" << Stub
+ << "] for external function at '" << FnAddr << "'\n");
return Stub;
}
@@ -276,7 +281,8 @@ unsigned JITResolver::getGOTIndexForAddr(void* addr) {
if (!idx) {
idx = ++nextGOTIndex;
revGOTMap[addr] = idx;
- DOUT << "JIT: Adding GOT entry " << idx << " for addr [" << addr << "]\n";
+ DEBUG(errs() << "JIT: Adding GOT entry " << idx << " for addr ["
+ << addr << "]\n");
}
return idx;
}
@@ -373,9 +379,8 @@ void *JITResolver::JITCompilerFn(void *Stub) {
// If lazy compilation is disabled, emit a useful error message and abort.
if (TheJIT->isLazyCompilationDisabled()) {
- cerr << "LLVM JIT requested to do lazy compilation of function '"
- << F->getName() << "' when lazy compiles are disabled!\n";
- abort();
+ llvm_report_error("LLVM JIT requested to do lazy compilation of function '"
+ + F->getName() + "' when lazy compiles are disabled!");
}
// We might like to remove the stub from the StubToFunction map.
@@ -385,9 +390,9 @@ void *JITResolver::JITCompilerFn(void *Stub) {
// it needs to call.
//JR.state.getStubToFunctionMap(locked).erase(I);
- DOUT << "JIT: Lazily resolving function '" << F->getName()
- << "' In stub ptr = " << Stub << " actual ptr = "
- << ActualPtr << "\n";
+ DEBUG(errs() << "JIT: Lazily resolving function '" << F->getName()
+ << "' In stub ptr = " << Stub << " actual ptr = "
+ << ActualPtr << "\n");
Result = TheJIT->getPointerToFunction(F);
}
@@ -424,6 +429,12 @@ namespace {
// save BufferBegin/BufferEnd/CurBufferPtr here.
uint8_t *SavedBufferBegin, *SavedBufferEnd, *SavedCurBufferPtr;
+ // When reattempting to JIT a function after running out of space, we store
+ // the estimated size of the function we're trying to JIT here, so we can
+ // ask the memory manager for at least this much space. When we
+ // successfully emit the function, we reset this back to zero.
+ uintptr_t SizeEstimate;
+
/// Relocations - These are the relocations that the function needs, as
/// emitted.
std::vector<MachineRelocation> Relocations;
@@ -455,9 +466,12 @@ namespace {
/// Resolver - This contains info about the currently resolved functions.
JITResolver Resolver;
-
+
/// DE - The dwarf emitter for the jit.
- JITDwarfEmitter *DE;
+ OwningPtr<JITDwarfEmitter> DE;
+
+ /// DR - The debug registerer for the jit.
+ OwningPtr<JITDebugRegisterer> DR;
/// LabelLocations - This vector is a mapping from Label ID's to their
/// address.
@@ -472,7 +486,12 @@ namespace {
// CurFn - The llvm function being emitted. Only valid during
// finishFunction().
const Function *CurFn;
-
+
+ /// Information about emitted code, which is passed to the
+ /// JITEventListeners. This is reset in startFunction and used in
+ /// finishFunction.
+ JITEvent_EmittedFunctionDetails EmissionDetails;
+
// CurFnStubUses - For a given Function, a vector of stubs that it
// references. This facilitates the JIT detecting that a stub is no
// longer used, so that it may be deallocated.
@@ -487,19 +506,26 @@ namespace {
// in the JITResolver's ExternalFnToStubMap.
StringMap<void *> ExtFnStubs;
+ DebugLocTuple PrevDLT;
+
public:
- JITEmitter(JIT &jit, JITMemoryManager *JMM) : Resolver(jit), CurFn(0) {
+ JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM)
+ : SizeEstimate(0), Resolver(jit), MMI(0), CurFn(0) {
MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager();
if (jit.getJITInfo().needsGOT()) {
MemMgr->AllocateGOT();
- DOUT << "JIT is managing a GOT\n";
+ DEBUG(errs() << "JIT is managing a GOT\n");
}
- if (ExceptionHandling) DE = new JITDwarfEmitter(jit);
+ if (DwarfExceptionHandling || JITEmitDebugInfo) {
+ DE.reset(new JITDwarfEmitter(jit));
+ }
+ if (JITEmitDebugInfo) {
+ DR.reset(new JITDebugRegisterer(TM));
+ }
}
~JITEmitter() {
delete MemMgr;
- if (ExceptionHandling) delete DE;
}
/// classof - Methods for support type inquiry through isa, cast, and
@@ -527,6 +553,11 @@ namespace {
/// allocate a new one of the given size.
virtual void *allocateSpace(uintptr_t Size, unsigned Alignment);
+ /// allocateGlobal - Allocate memory for a global. Unlike allocateSpace,
+ /// this method does not allocate memory in the current output buffer,
+ /// because a global may live longer than the current function.
+ virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment);
+
virtual void addRelocation(const MachineRelocation &MR) {
Relocations.push_back(MR);
}
@@ -535,8 +566,8 @@ namespace {
if (MBBLocations.size() <= (unsigned)MBB->getNumber())
MBBLocations.resize((MBB->getNumber()+1)*2);
MBBLocations[MBB->getNumber()] = getCurrentPCValue();
- DOUT << "JIT: Emitting BB" << MBB->getNumber() << " at ["
- << (void*) getCurrentPCValue() << "]\n";
+ DEBUG(errs() << "JIT: Emitting BB" << MBB->getNumber() << " at ["
+ << (void*) getCurrentPCValue() << "]\n");
}
virtual uintptr_t getConstantPoolEntryAddress(unsigned Entry) const;
@@ -548,9 +579,14 @@ namespace {
return MBBLocations[MBB->getNumber()];
}
+ /// retryWithMoreMemory - Log a retry and deallocate all memory for the
+ /// given function. Increase the minimum allocation size so that we get
+ /// more memory next time.
+ void retryWithMoreMemory(MachineFunction &F);
+
/// deallocateMemForFunction - Deallocate all memory for the specified
/// function body.
- void deallocateMemForFunction(Function *F);
+ void deallocateMemForFunction(const Function *F);
/// AddStubToCurrentFunction - Mark the current function being JIT'd as
/// using the stub at the specified address. Allows
@@ -561,6 +597,8 @@ namespace {
/// MachineRelocations that reference external functions by name.
const StringMap<void*> &getExternalFnStubs() const { return ExtFnStubs; }
+ virtual void processDebugLoc(DebugLoc DL, bool BeforePrintingInsn);
+
virtual void emitLabel(uint64_t LabelID) {
if (LabelLocations.size() <= LabelID)
LabelLocations.resize((LabelID+1)*2);
@@ -575,14 +613,14 @@ namespace {
virtual void setModuleInfo(MachineModuleInfo* Info) {
MMI = Info;
- if (ExceptionHandling) DE->setModuleInfo(Info);
+ if (DE.get()) DE->setModuleInfo(Info);
}
- void setMemoryExecutable(void) {
+ void setMemoryExecutable() {
MemMgr->setMemoryExecutable();
}
- JITMemoryManager *getMemMgr(void) const { return MemMgr; }
+ JITMemoryManager *getMemMgr() const { return MemMgr; }
private:
void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub);
@@ -606,7 +644,7 @@ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference,
// If we have already compiled the function, return a pointer to its body.
Function *F = cast<Function>(V);
void *ResultPtr;
- if (!DoesntNeedStub && !TheJIT->isLazyCompilationDisabled()) {
+ if (!DoesntNeedStub) {
// Return the function stub if it's already created.
ResultPtr = Resolver.getFunctionStubIfAvailable(F);
if (ResultPtr)
@@ -658,11 +696,8 @@ void *JITEmitter::getPointerToGVIndirectSym(GlobalValue *V, void *Reference,
}
void JITEmitter::AddStubToCurrentFunction(void *StubAddr) {
- if (!TheJIT->areDlsymStubsEnabled())
- return;
-
assert(CurFn && "Stub added to current function, but current function is 0!");
-
+
SmallVectorImpl<void*> &StubsUsed = CurFnStubUses[CurFn];
StubsUsed.push_back(StubAddr);
@@ -670,6 +705,23 @@ void JITEmitter::AddStubToCurrentFunction(void *StubAddr) {
FnRefs.insert(CurFn);
}
+void JITEmitter::processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) {
+ if (!DL.isUnknown()) {
+ DebugLocTuple CurDLT = EmissionDetails.MF->getDebugLocTuple(DL);
+
+ if (BeforePrintingInsn) {
+ if (CurDLT.Scope != 0 && PrevDLT != CurDLT) {
+ JITEvent_EmittedFunctionDetails::LineStart NextLine;
+ NextLine.Address = getCurrentPCValue();
+ NextLine.Loc = DL;
+ EmissionDetails.LineStarts.push_back(NextLine);
+ }
+
+ PrevDLT = CurDLT;
+ }
+ }
+}
+
static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP,
const TargetData *TD) {
const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
@@ -713,7 +765,7 @@ unsigned JITEmitter::addSizeOfGlobal(const GlobalVariable *GV, unsigned Size) {
size_t GVSize = (size_t)TheJIT->getTargetData()->getTypeAllocSize(ElTy);
size_t GVAlign =
(size_t)TheJIT->getTargetData()->getPreferredAlignment(GV);
- DOUT << "JIT: Adding in size " << GVSize << " alignment " << GVAlign;
+ DEBUG(errs() << "JIT: Adding in size " << GVSize << " alignment " << GVAlign);
DEBUG(GV->dump());
// Assume code section ends with worst possible alignment, so first
// variable needs maximal padding.
@@ -772,8 +824,10 @@ unsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C,
break;
}
default: {
- cerr << "ConstantExpr not handled: " << *CE << "\n";
- abort();
+ std::string msg;
+ raw_string_ostream Msg(msg);
+ Msg << "ConstantExpr not handled: " << *CE;
+ llvm_report_error(Msg.str());
}
}
}
@@ -839,7 +893,7 @@ unsigned JITEmitter::GetSizeOfGlobalsInBytes(MachineFunction &MF) {
}
}
}
- DOUT << "JIT: About to look through initializers\n";
+ DEBUG(errs() << "JIT: About to look through initializers\n");
// Look for more globals that are referenced only from initializers.
// GVSet.end is computed each time because the set can grow as we go.
for (SmallPtrSet<const GlobalVariable *, 8>::iterator I = GVSet.begin();
@@ -853,14 +907,14 @@ unsigned JITEmitter::GetSizeOfGlobalsInBytes(MachineFunction &MF) {
}
void JITEmitter::startFunction(MachineFunction &F) {
- DOUT << "JIT: Starting CodeGen of Function "
- << F.getFunction()->getName() << "\n";
+ DEBUG(errs() << "JIT: Starting CodeGen of Function "
+ << F.getFunction()->getName() << "\n");
uintptr_t ActualSize = 0;
// Set the memory writable, if it's not already
MemMgr->setMemoryWritable();
if (MemMgr->NeedsExactSize()) {
- DOUT << "JIT: ExactSize\n";
+ DEBUG(errs() << "JIT: ExactSize\n");
const TargetInstrInfo* TII = F.getTarget().getInstrInfo();
MachineJumpTableInfo *MJTI = F.getJumpTableInfo();
MachineConstantPool *MCP = F.getConstantPool();
@@ -887,12 +941,15 @@ void JITEmitter::startFunction(MachineFunction &F) {
// Add the function size
ActualSize += TII->GetFunctionSizeInBytes(F);
- DOUT << "JIT: ActualSize before globals " << ActualSize << "\n";
+ DEBUG(errs() << "JIT: ActualSize before globals " << ActualSize << "\n");
// Add the size of the globals that will be allocated after this function.
// These are all the ones referenced from this function that were not
// previously allocated.
ActualSize += GetSizeOfGlobalsInBytes(F);
- DOUT << "JIT: ActualSize after globals " << ActualSize << "\n";
+ DEBUG(errs() << "JIT: ActualSize after globals " << ActualSize << "\n");
+ } else if (SizeEstimate > 0) {
+ // SizeEstimate will be non-zero on reallocation attempts.
+ ActualSize = SizeEstimate;
}
BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
@@ -910,17 +967,22 @@ void JITEmitter::startFunction(MachineFunction &F) {
TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr);
MBBLocations.clear();
+
+ EmissionDetails.MF = &F;
+ EmissionDetails.LineStarts.clear();
}
bool JITEmitter::finishFunction(MachineFunction &F) {
if (CurBufferPtr == BufferEnd) {
- // FIXME: Allocate more space, then try again.
- cerr << "JIT: Ran out of space for generated machine code!\n";
- abort();
+ // We must call endFunctionBody before retrying, because
+ // deallocateMemForFunction requires it.
+ MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
+ retryWithMoreMemory(F);
+ return true;
}
-
+
emitJumpTableInfo(F.getJumpTableInfo());
-
+
// FnStart is the start of the text, not the start of the constant pool and
// other per-function data.
uint8_t *FnStart =
@@ -941,8 +1003,8 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
if (MR.isExternalSymbol()) {
ResultPtr = TheJIT->getPointerToNamedFunction(MR.getExternalSymbol(),
false);
- DOUT << "JIT: Map \'" << MR.getExternalSymbol() << "\' to ["
- << ResultPtr << "]\n";
+ DEBUG(errs() << "JIT: Map \'" << MR.getExternalSymbol() << "\' to ["
+ << ResultPtr << "]\n");
// If the target REALLY wants a stub for this function, emit it now.
if (!MR.doesntNeedStub()) {
@@ -983,9 +1045,9 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
unsigned idx = Resolver.getGOTIndexForAddr(ResultPtr);
MR.setGOTIndex(idx);
if (((void**)MemMgr->getGOTBase())[idx] != ResultPtr) {
- DOUT << "JIT: GOT was out of date for " << ResultPtr
- << " pointing at " << ((void**)MemMgr->getGOTBase())[idx]
- << "\n";
+ DEBUG(errs() << "JIT: GOT was out of date for " << ResultPtr
+ << " pointing at " << ((void**)MemMgr->getGOTBase())[idx]
+ << "\n");
((void**)MemMgr->getGOTBase())[idx] = ResultPtr;
}
}
@@ -1000,8 +1062,9 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
if (MemMgr->isManagingGOT()) {
unsigned idx = Resolver.getGOTIndexForAddr((void*)BufferBegin);
if (((void**)MemMgr->getGOTBase())[idx] != (void*)BufferBegin) {
- DOUT << "JIT: GOT was out of date for " << (void*)BufferBegin
- << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] << "\n";
+ DEBUG(errs() << "JIT: GOT was out of date for " << (void*)BufferBegin
+ << " pointing at " << ((void**)MemMgr->getGOTBase())[idx]
+ << "\n");
((void**)MemMgr->getGOTBase())[idx] = (void*)BufferBegin;
}
}
@@ -1011,9 +1074,12 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
if (CurBufferPtr == BufferEnd) {
- // FIXME: Allocate more space, then try again.
- cerr << "JIT: Ran out of space for generated machine code!\n";
- abort();
+ retryWithMoreMemory(F);
+ return true;
+ } else {
+ // Now that we've succeeded in emitting the function, reset the
+ // SizeEstimate back down to zero.
+ SizeEstimate = 0;
}
BufferBegin = CurBufferPtr = 0;
@@ -1022,14 +1088,13 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
// Invalidate the icache if necessary.
sys::Memory::InvalidateInstructionCache(FnStart, FnEnd-FnStart);
- JITEvent_EmittedFunctionDetails Details;
TheJIT->NotifyFunctionEmitted(*F.getFunction(), FnStart, FnEnd-FnStart,
- Details);
+ EmissionDetails);
- DOUT << "JIT: Finished CodeGen of [" << (void*)FnStart
- << "] Function: " << F.getFunction()->getName()
- << ": " << (FnEnd-FnStart) << " bytes of text, "
- << Relocations.size() << " relocations\n";
+ DEBUG(errs() << "JIT: Finished CodeGen of [" << (void*)FnStart
+ << "] Function: " << F.getFunction()->getName()
+ << ": " << (FnEnd-FnStart) << " bytes of text, "
+ << Relocations.size() << " relocations\n");
Relocations.clear();
ConstPoolAddresses.clear();
@@ -1037,45 +1102,42 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
// Mark code region readable and executable if it's not so already.
MemMgr->setMemoryExecutable();
-#ifndef NDEBUG
- {
+ DEBUG(
if (sys::hasDisassembler()) {
- DOUT << "JIT: Disassembled code:\n";
- DOUT << sys::disassembleBuffer(FnStart, FnEnd-FnStart, (uintptr_t)FnStart);
+ errs() << "JIT: Disassembled code:\n";
+ errs() << sys::disassembleBuffer(FnStart, FnEnd-FnStart,
+ (uintptr_t)FnStart);
} else {
- DOUT << "JIT: Binary code:\n";
- DOUT << std::hex;
+ errs() << "JIT: Binary code:\n";
uint8_t* q = FnStart;
for (int i = 0; q < FnEnd; q += 4, ++i) {
if (i == 4)
i = 0;
if (i == 0)
- DOUT << "JIT: " << std::setw(8) << std::setfill('0')
- << (long)(q - FnStart) << ": ";
+ errs() << "JIT: " << (long)(q - FnStart) << ": ";
bool Done = false;
for (int j = 3; j >= 0; --j) {
if (q + j >= FnEnd)
Done = true;
else
- DOUT << std::setw(2) << std::setfill('0') << (unsigned short)q[j];
+ errs() << (unsigned short)q[j];
}
if (Done)
break;
- DOUT << ' ';
+ errs() << ' ';
if (i == 3)
- DOUT << '\n';
+ errs() << '\n';
}
- DOUT << std::dec;
- DOUT<< '\n';
+ errs()<< '\n';
}
- }
-#endif
- if (ExceptionHandling) {
+ );
+
+ if (DwarfExceptionHandling || JITEmitDebugInfo) {
uintptr_t ActualSize = 0;
SavedBufferBegin = BufferBegin;
SavedBufferEnd = BufferEnd;
SavedCurBufferPtr = CurBufferPtr;
-
+
if (MemMgr->NeedsExactSize()) {
ActualSize = DE->GetDwarfTableSizeInBytes(F, *this, FnStart, FnEnd);
}
@@ -1083,14 +1145,28 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
ActualSize);
BufferEnd = BufferBegin+ActualSize;
- uint8_t* FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd);
+ uint8_t *EhStart;
+ uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd,
+ EhStart);
MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr,
FrameRegister);
+ uint8_t *EhEnd = CurBufferPtr;
BufferBegin = SavedBufferBegin;
BufferEnd = SavedBufferEnd;
CurBufferPtr = SavedCurBufferPtr;
- TheJIT->RegisterTable(FrameRegister);
+ if (DwarfExceptionHandling) {
+ TheJIT->RegisterTable(FrameRegister);
+ }
+
+ if (JITEmitDebugInfo) {
+ DebugInfo I;
+ I.FnStart = FnStart;
+ I.FnEnd = FnEnd;
+ I.EhStart = EhStart;
+ I.EhEnd = EhEnd;
+ DR->RegisterFunction(F.getFunction(), I);
+ }
}
if (MMI)
@@ -1099,11 +1175,28 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
return false;
}
+void JITEmitter::retryWithMoreMemory(MachineFunction &F) {
+ DEBUG(errs() << "JIT: Ran out of space for native code. Reattempting.\n");
+ Relocations.clear(); // Clear the old relocations or we'll reapply them.
+ ConstPoolAddresses.clear();
+ ++NumRetries;
+ deallocateMemForFunction(F.getFunction());
+ // Try again with at least twice as much free space.
+ SizeEstimate = (uintptr_t)(2 * (BufferEnd - BufferBegin));
+}
+
/// deallocateMemForFunction - Deallocate all memory for the specified
/// function body. Also drop any references the function has to stubs.
-void JITEmitter::deallocateMemForFunction(Function *F) {
+void JITEmitter::deallocateMemForFunction(const Function *F) {
MemMgr->deallocateMemForFunction(F);
+ // TODO: Do we need to unregister exception handling information from libgcc
+ // here?
+
+ if (JITEmitDebugInfo) {
+ DR->UnregisterFunction(F);
+ }
+
// If the function did not reference any stubs, return.
if (CurFnStubUses.find(F) == CurFnStubUses.end())
return;
@@ -1125,7 +1218,7 @@ void JITEmitter::deallocateMemForFunction(Function *F) {
// in the JITResolver. Were there a memory manager deallocateStub routine,
// we could call that at this point too.
if (FnRefs.empty()) {
- DOUT << "\nJIT: Invalidated Stub at [" << Stub << "]\n";
+ DEBUG(errs() << "\nJIT: Invalidated Stub at [" << Stub << "]\n");
StubFnRefs.erase(Stub);
// Invalidate the stub. If it is a GV stub, update the JIT's global
@@ -1161,6 +1254,11 @@ void* JITEmitter::allocateSpace(uintptr_t Size, unsigned Alignment) {
return CurBufferPtr;
}
+void* JITEmitter::allocateGlobal(uintptr_t Size, unsigned Alignment) {
+ // Delegate this call through the memory manager.
+ return MemMgr->allocateGlobal(Size, Alignment);
+}
+
void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
if (TheJIT->getJITInfo().hasCustomConstantPool())
return;
@@ -1175,8 +1273,8 @@ void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
if (ConstantPoolBase == 0) return; // Buffer overflow.
- DOUT << "JIT: Emitted constant pool at [" << ConstantPoolBase
- << "] (size: " << Size << ", alignment: " << Align << ")\n";
+ DEBUG(errs() << "JIT: Emitted constant pool at [" << ConstantPoolBase
+ << "] (size: " << Size << ", alignment: " << Align << ")\n");
// Initialize the memory for all of the constant pool entries.
unsigned Offset = 0;
@@ -1189,13 +1287,12 @@ void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
ConstPoolAddresses.push_back(CAddr);
if (CPE.isMachineConstantPoolEntry()) {
// FIXME: add support to lower machine constant pool values into bytes!
- cerr << "Initialize memory with machine specific constant pool entry"
- << " has not been implemented!\n";
- abort();
+ llvm_report_error("Initialize memory with machine specific constant pool"
+ "entry has not been implemented!");
}
TheJIT->InitializeMemory(CPE.Val.ConstVal, (void*)CAddr);
- DOUT << "JIT: CP" << i << " at [0x"
- << std::hex << CAddr << std::dec << "]\n";
+ DEBUG(errs() << "JIT: CP" << i << " at [0x";
+ errs().write_hex(CAddr) << "]\n");
const Type *Ty = CPE.Val.ConstVal->getType();
Offset += TheJIT->getTargetData()->getTypeAllocSize(Ty);
@@ -1322,8 +1419,9 @@ uintptr_t JITEmitter::getJumpTableEntryAddress(unsigned Index) const {
// Public interface to this file
//===----------------------------------------------------------------------===//
-JITCodeEmitter *JIT::createEmitter(JIT &jit, JITMemoryManager *JMM) {
- return new JITEmitter(jit, JMM);
+JITCodeEmitter *JIT::createEmitter(JIT &jit, JITMemoryManager *JMM,
+ TargetMachine &tm) {
+ return new JITEmitter(jit, JMM, tm);
}
// getPointerToNamedFunction - This function is used as a global wrapper to
@@ -1396,7 +1494,7 @@ void JIT::updateDlsymStubTable() {
SmallVector<unsigned, 8> Offsets;
for (unsigned i = 0; i != GVs.size(); ++i) {
Offsets.push_back(offset);
- offset += GVs[i]->getName().length() + 1;
+ offset += GVs[i]->getName().size() + 1;
}
for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end();
i != e; ++i) {
OpenPOWER on IntegriCloud