#include "llvm/Support/Debug.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/System/Disassembler.h"
+#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/Statistic.h"
#include <algorithm>
using namespace llvm;
JITResolver *JITResolver::TheJITResolver = 0;
-#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
- defined(__APPLE__)
-extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
-#endif
-
-/// synchronizeICache - On some targets, the JIT emitted code must be
-/// explicitly refetched to ensure correct execution.
-static void synchronizeICache(const void *Addr, size_t len) {
-#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
- defined(__APPLE__)
- sys_icache_invalidate(Addr, len);
-#endif
-}
-
/// getFunctionStub - This returns a pointer to a function stub, creating
/// one on demand as needed.
void *JITResolver::getFunctionStub(Function *F) {
// Otherwise, codegen a new stub. For now, the stub will call the lazy
// resolver function.
- Stub = TheJIT->getJITInfo().emitFunctionStub(Actual,
+ Stub = TheJIT->getJITInfo().emitFunctionStub(F, Actual,
*TheJIT->getCodeEmitter());
if (Actual != (void*)(intptr_t)LazyResolverFn) {
if (LazyPtr) return LazyPtr;
// Otherwise, codegen a new lazy pointer.
- LazyPtr = TheJIT->getJITInfo().emitGlobalValueLazyPtr(GVAddress,
+ LazyPtr = TheJIT->getJITInfo().emitGlobalValueLazyPtr(GV, GVAddress,
*TheJIT->getCodeEmitter());
DOUT << "JIT: Stub emitted at [" << LazyPtr << "] for GV '"
void *&Stub = ExternalFnToStubMap[FnAddr];
if (Stub) return Stub;
- Stub = TheJIT->getJITInfo().emitFunctionStub(FnAddr,
+ Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr,
*TheJIT->getCodeEmitter());
DOUT << "JIT: Stub emitted at [" << Stub
// have useful answers. However, we don't go crazy with atomic operations, we
// just do a "reasonable effort".
#ifdef __APPLE__
-#define ENABLE_JIT_SYMBOL_TABLE 1
+#define ENABLE_JIT_SYMBOL_TABLE 0
#endif
/// JitSymbolEntry - Each function that is JIT compiled results in one of these
--SymTabPtr->NumSymbols;
// Finally, if we deleted the final symbol, deallocate the table itself.
- if (SymTabPtr->NumSymbols == 0)
+ if (SymTabPtr->NumSymbols != 0)
return;
*SymTabPtrPtr = 0;
void initJumpTableInfo(MachineJumpTableInfo *MJTI);
void emitJumpTableInfo(MachineJumpTableInfo *MJTI);
- virtual void startFunctionStub(unsigned StubSize, unsigned Alignment = 1);
- virtual void* finishFunctionStub(const Function *F);
+ virtual void startFunctionStub(const GlobalValue* F, unsigned StubSize,
+ unsigned Alignment = 1);
+ virtual void* finishFunctionStub(const GlobalValue *F);
virtual void addRelocation(const MachineRelocation &MR) {
Relocations.push_back(MR);
return Resolver.getGlobalValueLazyPtr(V, GVAddress);
}
+static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP) {
+ const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
+ if (Constants.empty()) return 0;
+
+ MachineConstantPoolEntry CPE = Constants.back();
+ unsigned Size = CPE.Offset;
+ const Type *Ty = CPE.isMachineConstantPoolEntry()
+ ? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType();
+ Size += TheJIT->getTargetData()->getABITypeSize(Ty);
+ return Size;
+}
+
+static unsigned GetJumpTableSizeInBytes(MachineJumpTableInfo *MJTI) {
+ const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
+ if (JT.empty()) return 0;
+
+ unsigned NumEntries = 0;
+ for (unsigned i = 0, e = JT.size(); i != e; ++i)
+ NumEntries += JT[i].MBBs.size();
+
+ unsigned EntrySize = MJTI->getEntrySize();
+
+ return NumEntries * EntrySize;
+}
+
+static uintptr_t RoundUpToAlign(uintptr_t Size, unsigned Alignment) {
+ if (Alignment == 0) Alignment = 1;
+ // Since we do not know where the buffer will be allocated, be pessimistic.
+ return Size + Alignment;
+}
void JITEmitter::startFunction(MachineFunction &F) {
- uintptr_t ActualSize;
+ uintptr_t ActualSize = 0;
+ if (MemMgr->NeedsExactSize()) {
+ const TargetInstrInfo* TII = F.getTarget().getInstrInfo();
+ MachineJumpTableInfo *MJTI = F.getJumpTableInfo();
+ MachineConstantPool *MCP = F.getConstantPool();
+
+ // Ensure the constant pool/jump table info is at least 4-byte aligned.
+ ActualSize = RoundUpToAlign(ActualSize, 16);
+
+ // Add the alignment of the constant pool
+ ActualSize = RoundUpToAlign(ActualSize,
+ 1 << MCP->getConstantPoolAlignment());
+
+ // Add the constant pool size
+ ActualSize += GetConstantPoolSizeInBytes(MCP);
+
+ // Add the aligment of the jump table info
+ ActualSize = RoundUpToAlign(ActualSize, MJTI->getAlignment());
+
+ // Add the jump table size
+ ActualSize += GetJumpTableSizeInBytes(MJTI);
+
+ // Add the alignment for the function
+ ActualSize = RoundUpToAlign(ActualSize,
+ std::max(F.getFunction()->getAlignment(), 8U));
+
+ // Add the function size
+ ActualSize += TII->GetFunctionSizeInBytes(F);
+ }
+
BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
ActualSize);
BufferEnd = BufferBegin+ActualSize;
}
// Invalidate the icache if necessary.
- synchronizeICache(FnStart, FnEnd-FnStart);
+ TheJIT->getJITInfo().InvalidateInstructionCache(FnStart, FnEnd-FnStart);
// Add it to the JIT symbol table if the host wants it.
AddFunctionToSymbolTable(F.getFunction()->getNameStart(),
<< sys::disassembleBuffer(FnStart, FnEnd-FnStart, (uintptr_t)FnStart);
#endif
if (ExceptionHandling) {
- uintptr_t ActualSize;
+ uintptr_t ActualSize = 0;
SavedBufferBegin = BufferBegin;
SavedBufferEnd = BufferEnd;
SavedCurBufferPtr = CurBufferPtr;
+
+ if (MemMgr->NeedsExactSize()) {
+ ActualSize = DE->GetDwarfTableSizeInBytes(F, *this, FnStart, FnEnd);
+ }
BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
ActualSize);
}
}
-void JITEmitter::startFunctionStub(unsigned StubSize, unsigned Alignment) {
+void JITEmitter::startFunctionStub(const GlobalValue* F, unsigned StubSize,
+ unsigned Alignment) {
SavedBufferBegin = BufferBegin;
SavedBufferEnd = BufferEnd;
SavedCurBufferPtr = CurBufferPtr;
- BufferBegin = CurBufferPtr = MemMgr->allocateStub(StubSize, Alignment);
+ BufferBegin = CurBufferPtr = MemMgr->allocateStub(F, StubSize, Alignment);
BufferEnd = BufferBegin+StubSize+1;
}
-void *JITEmitter::finishFunctionStub(const Function *F) {
+void *JITEmitter::finishFunctionStub(const GlobalValue* F) {
NumBytes += getCurrentPCOffset();
std::swap(SavedBufferBegin, BufferBegin);
BufferEnd = SavedBufferEnd;