aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/JITCodeEmitter.h28
-rw-r--r--include/llvm/CodeGen/MachineCodeEmitter.h61
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp68
-rw-r--r--lib/Target/ARM/ARMJITInfo.cpp16
-rw-r--r--lib/Target/Alpha/AlphaJITInfo.cpp1
-rw-r--r--lib/Target/PowerPC/PPCJITInfo.cpp1
-rw-r--r--lib/Target/X86/X86JITInfo.cpp18
7 files changed, 85 insertions, 108 deletions
diff --git a/include/llvm/CodeGen/JITCodeEmitter.h b/include/llvm/CodeGen/JITCodeEmitter.h
index ea3e59b..9c4e5b9 100644
--- a/include/llvm/CodeGen/JITCodeEmitter.h
+++ b/include/llvm/CodeGen/JITCodeEmitter.h
@@ -68,29 +68,11 @@ public:
///
virtual bool finishFunction(MachineFunction &F) = 0;
- /// startGVStub - This callback is invoked when the JIT needs the address of a
- /// GV (e.g. function) that has not been code generated yet. The StubSize
- /// specifies the total size required by the stub. The BufferState must be
- /// passed to finishGVStub, and start/finish pairs with the same BufferState
- /// must be properly nested.
- ///
- virtual void startGVStub(BufferState &BS, const GlobalValue* GV,
- unsigned StubSize, unsigned Alignment = 1) = 0;
-
- /// startGVStub - This callback is invoked when the JIT needs the address of a
- /// GV (e.g. function) that has not been code generated yet. Buffer points to
- /// memory already allocated for this stub. The BufferState must be passed to
- /// finishGVStub, and start/finish pairs with the same BufferState must be
- /// properly nested.
- ///
- virtual void startGVStub(BufferState &BS, void *Buffer,
- unsigned StubSize) = 0;
-
- /// finishGVStub - This callback is invoked to terminate a GV stub and returns
- /// the start address of the stub. The BufferState must first have been
- /// passed to startGVStub.
- ///
- virtual void *finishGVStub(BufferState &BS) = 0;
+ /// allocIndirectGV - Allocates and fills storage for an indirect
+ /// GlobalValue, and returns the address.
+ virtual void *allocIndirectGV(const GlobalValue *GV,
+ const uint8_t *Buffer, size_t Size,
+ unsigned Alignment) = 0;
/// emitByte - This callback is invoked when a byte needs to be written to the
/// output stream.
diff --git a/include/llvm/CodeGen/MachineCodeEmitter.h b/include/llvm/CodeGen/MachineCodeEmitter.h
index 791db00..d598a93 100644
--- a/include/llvm/CodeGen/MachineCodeEmitter.h
+++ b/include/llvm/CodeGen/MachineCodeEmitter.h
@@ -48,41 +48,16 @@ class Function;
/// occurred, more memory is allocated, and we reemit the code into it.
///
class MachineCodeEmitter {
-public:
- class BufferState {
- friend class MachineCodeEmitter;
- /// BufferBegin/BufferEnd - Pointers to the start and end of the memory
- /// allocated for this code buffer.
- uint8_t *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).
- uint8_t *CurBufferPtr;
- public:
- BufferState() : BufferBegin(NULL), BufferEnd(NULL), CurBufferPtr(NULL) {}
- };
-
protected:
- /// These have the same meanings as the fields in BufferState
- uint8_t *BufferBegin, *BufferEnd, *CurBufferPtr;
-
- /// Save or restore the current buffer state. The BufferState objects must be
- /// used as a stack.
- void SaveStateTo(BufferState &BS) {
- assert(BS.BufferBegin == NULL &&
- "Can't save state into the same BufferState twice.");
- BS.BufferBegin = BufferBegin;
- BS.BufferEnd = BufferEnd;
- BS.CurBufferPtr = CurBufferPtr;
- }
- void RestoreStateFrom(BufferState &BS) {
- BufferBegin = BS.BufferBegin;
- BufferEnd = BS.BufferEnd;
- CurBufferPtr = BS.CurBufferPtr;
- }
+ /// BufferBegin/BufferEnd - Pointers to the start and end of the memory
+ /// allocated for this code buffer.
+ uint8_t *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).
+ uint8_t *CurBufferPtr;
public:
virtual ~MachineCodeEmitter() {}
@@ -113,15 +88,23 @@ public:
///
void emitWordLE(uint32_t W) {
if (4 <= BufferEnd-CurBufferPtr) {
- *CurBufferPtr++ = (uint8_t)(W >> 0);
- *CurBufferPtr++ = (uint8_t)(W >> 8);
- *CurBufferPtr++ = (uint8_t)(W >> 16);
- *CurBufferPtr++ = (uint8_t)(W >> 24);
+ emitWordLEInto(CurBufferPtr, W);
} else {
CurBufferPtr = BufferEnd;
}
}
-
+
+ /// emitWordLEInto - This callback is invoked when a 32-bit word needs to be
+ /// written to an arbitrary buffer in little-endian format. Buf must have at
+ /// least 4 bytes of available space.
+ ///
+ static void emitWordLEInto(uint8_t *&Buf, uint32_t W) {
+ *Buf++ = (uint8_t)(W >> 0);
+ *Buf++ = (uint8_t)(W >> 8);
+ *Buf++ = (uint8_t)(W >> 16);
+ *Buf++ = (uint8_t)(W >> 24);
+ }
+
/// emitWordBE - This callback is invoked when a 32-bit word needs to be
/// written to the output stream in big-endian format.
///
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index bbac762..a670772 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -271,6 +271,10 @@ namespace {
class JITEmitter : public JITCodeEmitter {
JITMemoryManager *MemMgr;
+ // When outputting a function stub in the context of some other function, we
+ // 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
@@ -396,11 +400,13 @@ namespace {
void initJumpTableInfo(MachineJumpTableInfo *MJTI);
void emitJumpTableInfo(MachineJumpTableInfo *MJTI);
- virtual void startGVStub(BufferState &BS, const GlobalValue* GV,
- unsigned StubSize, unsigned Alignment = 1);
- virtual void startGVStub(BufferState &BS, void *Buffer,
- unsigned StubSize);
- virtual void* finishGVStub(BufferState &BS);
+ void startGVStub(const GlobalValue* GV,
+ unsigned StubSize, unsigned Alignment = 1);
+ void startGVStub(void *Buffer, unsigned StubSize);
+ void finishGVStub();
+ virtual void *allocIndirectGV(const GlobalValue *GV,
+ const uint8_t *Buffer, size_t Size,
+ unsigned Alignment);
/// allocateSpace - Reserves space in the current block if any, or
/// allocate a new one of the given size.
@@ -521,13 +527,12 @@ void *JITResolver::getLazyFunctionStub(Function *F) {
if (!Actual) return 0;
}
- MachineCodeEmitter::BufferState BS;
TargetJITInfo::StubLayout SL = TheJIT->getJITInfo().getStubLayout();
- JE.startGVStub(BS, F, SL.Size, SL.Alignment);
+ JE.startGVStub(F, SL.Size, SL.Alignment);
// Codegen a new stub, calling the lazy resolver or the actual address of the
// external function, if it was resolved.
Stub = TheJIT->getJITInfo().emitFunctionStub(F, Actual, JE);
- JE.finishGVStub(BS);
+ JE.finishGVStub();
if (Actual != (void*)(intptr_t)LazyResolverFn) {
// If we are getting the stub for an external function, we really want the
@@ -579,11 +584,10 @@ void *JITResolver::getExternalFunctionStub(void *FnAddr) {
void *&Stub = ExternalFnToStubMap[FnAddr];
if (Stub) return Stub;
- MachineCodeEmitter::BufferState BS;
TargetJITInfo::StubLayout SL = TheJIT->getJITInfo().getStubLayout();
- JE.startGVStub(BS, 0, SL.Size, SL.Alignment);
+ JE.startGVStub(0, SL.Size, SL.Alignment);
Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr, JE);
- JE.finishGVStub(BS);
+ JE.finishGVStub();
DEBUG(errs() << "JIT: Stub emitted at [" << Stub
<< "] for external function at '" << FnAddr << "'\n");
@@ -1215,8 +1219,9 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
if (DwarfExceptionHandling || JITEmitDebugInfo) {
uintptr_t ActualSize = 0;
- BufferState BS;
- SaveStateTo(BS);
+ SavedBufferBegin = BufferBegin;
+ SavedBufferEnd = BufferEnd;
+ SavedCurBufferPtr = CurBufferPtr;
if (MemMgr->NeedsExactSize()) {
ActualSize = DE->GetDwarfTableSizeInBytes(F, *this, FnStart, FnEnd);
@@ -1232,7 +1237,9 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr,
FrameRegister);
uint8_t *EhEnd = CurBufferPtr;
- RestoreStateFrom(BS);
+ BufferBegin = SavedBufferBegin;
+ BufferEnd = SavedBufferEnd;
+ CurBufferPtr = SavedCurBufferPtr;
if (DwarfExceptionHandling) {
TheJIT->RegisterTable(FrameRegister);
@@ -1438,27 +1445,39 @@ void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) {
}
}
-void JITEmitter::startGVStub(BufferState &BS, const GlobalValue* GV,
+void JITEmitter::startGVStub(const GlobalValue* GV,
unsigned StubSize, unsigned Alignment) {
- SaveStateTo(BS);
+ SavedBufferBegin = BufferBegin;
+ SavedBufferEnd = BufferEnd;
+ SavedCurBufferPtr = CurBufferPtr;
BufferBegin = CurBufferPtr = MemMgr->allocateStub(GV, StubSize, Alignment);
BufferEnd = BufferBegin+StubSize+1;
}
-void JITEmitter::startGVStub(BufferState &BS, void *Buffer, unsigned StubSize) {
- SaveStateTo(BS);
+void JITEmitter::startGVStub(void *Buffer, unsigned StubSize) {
+ SavedBufferBegin = BufferBegin;
+ SavedBufferEnd = BufferEnd;
+ SavedCurBufferPtr = CurBufferPtr;
BufferBegin = CurBufferPtr = (uint8_t *)Buffer;
BufferEnd = BufferBegin+StubSize+1;
}
-void *JITEmitter::finishGVStub(BufferState &BS) {
+void JITEmitter::finishGVStub() {
assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
NumBytes += getCurrentPCOffset();
- void *Result = BufferBegin;
- RestoreStateFrom(BS);
- return Result;
+ BufferBegin = SavedBufferBegin;
+ BufferEnd = SavedBufferEnd;
+ CurBufferPtr = SavedCurBufferPtr;
+}
+
+void *JITEmitter::allocIndirectGV(const GlobalValue *GV,
+ const uint8_t *Buffer, size_t Size,
+ unsigned Alignment) {
+ uint8_t *IndGV = MemMgr->allocateStub(GV, Size, Alignment);
+ memcpy(IndGV, Buffer, Size);
+ return IndGV;
}
// getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry
@@ -1546,11 +1565,10 @@ void JIT::updateFunctionStub(Function *F) {
// Tell the target jit info to rewrite the stub at the specified address,
// rather than creating a new one.
- MachineCodeEmitter::BufferState BS;
TargetJITInfo::StubLayout layout = getJITInfo().getStubLayout();
- JE->startGVStub(BS, Stub, layout.Size);
+ JE->startGVStub(Stub, layout.Size);
getJITInfo().emitFunctionStub(F, Addr, *getCodeEmitter());
- JE->finishGVStub(BS);
+ JE->finishGVStub();
}
/// freeMachineCodeForFunction - release machine code memory for given Function.
diff --git a/lib/Target/ARM/ARMJITInfo.cpp b/lib/Target/ARM/ARMJITInfo.cpp
index aa50cfd..bef5a06 100644
--- a/lib/Target/ARM/ARMJITInfo.cpp
+++ b/lib/Target/ARM/ARMJITInfo.cpp
@@ -139,17 +139,11 @@ ARMJITInfo::getLazyResolverFunction(JITCompilerFn F) {
void *ARMJITInfo::emitGlobalValueIndirectSym(const GlobalValue *GV, void *Ptr,
JITCodeEmitter &JCE) {
- MachineCodeEmitter::BufferState BS;
- JCE.startGVStub(BS, GV, 4, 4);
- intptr_t Addr = (intptr_t)JCE.getCurrentPCValue();
- if (!sys::Memory::setRangeWritable((void*)Addr, 4)) {
- llvm_unreachable("ERROR: Unable to mark indirect symbol writable");
- }
- JCE.emitWordLE((intptr_t)Ptr);
- if (!sys::Memory::setRangeExecutable((void*)Addr, 4)) {
- llvm_unreachable("ERROR: Unable to mark indirect symbol executable");
- }
- void *PtrAddr = JCE.finishGVStub(BS);
+ uint8_t Buffer[4];
+ uint8_t *Cur = Buffer;
+ MachineCodeEmitter::emitWordLEInto(Cur, (intptr_t)Ptr);
+ void *PtrAddr = JCE.allocIndirectGV(
+ GV, Buffer, sizeof(Buffer), /*Alignment=*/4);
addIndirectSymAddr(Ptr, (intptr_t)PtrAddr);
return PtrAddr;
}
diff --git a/lib/Target/Alpha/AlphaJITInfo.cpp b/lib/Target/Alpha/AlphaJITInfo.cpp
index b3b711e..cb8eb51 100644
--- a/lib/Target/Alpha/AlphaJITInfo.cpp
+++ b/lib/Target/Alpha/AlphaJITInfo.cpp
@@ -202,7 +202,6 @@ TargetJITInfo::StubLayout AlphaJITInfo::getStubLayout() {
void *AlphaJITInfo::emitFunctionStub(const Function* F, void *Fn,
JITCodeEmitter &JCE) {
- MachineCodeEmitter::BufferState BS;
//assert(Fn == AlphaCompilationCallback && "Where are you going?\n");
//Do things in a stupid slow way!
void* Addr = (void*)(intptr_t)JCE.getCurrentPCValue();
diff --git a/lib/Target/PowerPC/PPCJITInfo.cpp b/lib/Target/PowerPC/PPCJITInfo.cpp
index c679bcd..be6e51e 100644
--- a/lib/Target/PowerPC/PPCJITInfo.cpp
+++ b/lib/Target/PowerPC/PPCJITInfo.cpp
@@ -339,7 +339,6 @@ extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
void *PPCJITInfo::emitFunctionStub(const Function* F, void *Fn,
JITCodeEmitter &JCE) {
- MachineCodeEmitter::BufferState BS;
// If this is just a call to an external function, emit a branch instead of a
// call. The code is the same except for one bit of the last instruction.
if (Fn != (void*)(intptr_t)PPC32CompilationCallback &&
diff --git a/lib/Target/X86/X86JITInfo.cpp b/lib/Target/X86/X86JITInfo.cpp
index ce06f0f..c69cc83 100644
--- a/lib/Target/X86/X86JITInfo.cpp
+++ b/lib/Target/X86/X86JITInfo.cpp
@@ -426,16 +426,19 @@ X86JITInfo::X86JITInfo(X86TargetMachine &tm) : TM(tm) {
void *X86JITInfo::emitGlobalValueIndirectSym(const GlobalValue* GV, void *ptr,
JITCodeEmitter &JCE) {
- MachineCodeEmitter::BufferState BS;
#if defined (X86_64_JIT)
- JCE.startGVStub(BS, GV, 8, 8);
- JCE.emitWordLE((unsigned)(intptr_t)ptr);
- JCE.emitWordLE((unsigned)(((intptr_t)ptr) >> 32));
+ const unsigned Alignment = 8;
+ uint8_t Buffer[8];
+ uint8_t *Cur = Buffer;
+ MachineCodeEmitter::emitWordLEInto(Cur, (unsigned)(intptr_t)ptr);
+ MachineCodeEmitter::emitWordLEInto(Cur, (unsigned)(((intptr_t)ptr) >> 32));
#else
- JCE.startGVStub(BS, GV, 4, 4);
- JCE.emitWordLE((intptr_t)ptr);
+ const unsigned Alignment = 4;
+ uint8_t Buffer[4];
+ uint8_t *Cur = Buffer;
+ MachineCodeEmitter::emitWordLEInto(Cur, (intptr_t)ptr);
#endif
- return JCE.finishGVStub(BS);
+ return JCE.allocIndirectGV(GV, Buffer, sizeof(Buffer), Alignment);
}
TargetJITInfo::StubLayout X86JITInfo::getStubLayout() {
@@ -451,7 +454,6 @@ TargetJITInfo::StubLayout X86JITInfo::getStubLayout() {
void *X86JITInfo::emitFunctionStub(const Function* F, void *Target,
JITCodeEmitter &JCE) {
- MachineCodeEmitter::BufferState BS;
// Note, we cast to intptr_t here to silence a -pedantic warning that
// complains about casting a function pointer to a normal pointer.
#if defined (X86_32_JIT) && !defined (_MSC_VER)