Skip to content

Commit 3f23cef

Browse files
author
Andrew Kaylor
committed
Clean-up of memory buffer and object ownership model in MCJIT
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165053 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 9fd3046 commit 3f23cef

15 files changed

+311
-163
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//===---- ObjectBuffer.h - Utility class to wrap object image memory -----===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file declares a wrapper class to hold the memory into which an
11+
// object will be generated.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H
16+
#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H
17+
18+
#include "llvm/ADT/SmallVector.h"
19+
#include "llvm/ADT/OwningPtr.h"
20+
#include "llvm/Support/raw_ostream.h"
21+
#include "llvm/Support/MemoryBuffer.h"
22+
23+
namespace llvm {
24+
25+
/// ObjectBuffer - This class acts as a container for the memory buffer used during
26+
/// generation and loading of executable objects using MCJIT and RuntimeDyld. The
27+
/// underlying memory for the object will be owned by the ObjectBuffer instance
28+
/// throughout its lifetime. The getMemBuffer() method provides a way to create a
29+
/// MemoryBuffer wrapper object instance to be owned by other classes (such as
30+
/// ObjectFile) as needed, but the MemoryBuffer instance returned does not own the
31+
/// actual memory it points to.
32+
class ObjectBuffer {
33+
public:
34+
ObjectBuffer() {}
35+
ObjectBuffer(MemoryBuffer* Buf) : Buffer(Buf) {}
36+
virtual ~ObjectBuffer() {}
37+
38+
/// getMemBuffer - Like MemoryBuffer::getMemBuffer() this function
39+
/// returns a pointer to an object that is owned by the caller. However,
40+
/// the caller does not take ownership of the underlying memory.
41+
MemoryBuffer *getMemBuffer() const {
42+
return MemoryBuffer::getMemBuffer(Buffer->getBuffer(), "", false);
43+
}
44+
45+
const char *getBufferStart() const { return Buffer->getBufferStart(); }
46+
size_t getBufferSize() const { return Buffer->getBufferSize(); }
47+
48+
protected:
49+
// The memory contained in an ObjectBuffer
50+
OwningPtr<MemoryBuffer> Buffer;
51+
};
52+
53+
/// ObjectBufferStream - This class encapsulates the SmallVector and
54+
/// raw_svector_ostream needed to generate an object using MC code emission
55+
/// while providing a common ObjectBuffer interface for access to the
56+
/// memory once the object has been generated.
57+
class ObjectBufferStream : public ObjectBuffer {
58+
public:
59+
ObjectBufferStream() : OS(SV) {}
60+
virtual ~ObjectBufferStream() {}
61+
62+
raw_ostream &getOStream() { return OS; }
63+
void flush()
64+
{
65+
OS.flush();
66+
67+
// Make the data accessible via the ObjectBuffer::Buffer
68+
Buffer.reset(MemoryBuffer::getMemBuffer(StringRef(SV.data(), SV.size()),
69+
"",
70+
false));
71+
}
72+
73+
protected:
74+
SmallVector<char, 4096> SV; // Working buffer into which we JIT.
75+
raw_svector_ostream OS; // streaming wrapper
76+
};
77+
78+
} // namespace llvm
79+
80+
#endif
+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//===---- ObjectImage.h - Format independent executuable object image -----===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file declares a file format independent ObjectImage class.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_EXECUTIONENGINE_OBJECTIMAGE_H
15+
#define LLVM_EXECUTIONENGINE_OBJECTIMAGE_H
16+
17+
#include "llvm/Object/ObjectFile.h"
18+
#include "llvm/ExecutionEngine/ObjectBuffer.h"
19+
20+
namespace llvm {
21+
22+
23+
/// ObjectImage - A container class that represents an ObjectFile that has been
24+
/// or is in the process of being loaded into memory for execution.
25+
class ObjectImage {
26+
ObjectImage() LLVM_DELETED_FUNCTION;
27+
ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION;
28+
29+
protected:
30+
OwningPtr<ObjectBuffer> Buffer;
31+
32+
public:
33+
ObjectImage(ObjectBuffer *Input) : Buffer(Input) {}
34+
virtual ~ObjectImage() {}
35+
36+
virtual object::symbol_iterator begin_symbols() const = 0;
37+
virtual object::symbol_iterator end_symbols() const = 0;
38+
39+
virtual object::section_iterator begin_sections() const = 0;
40+
virtual object::section_iterator end_sections() const = 0;
41+
42+
virtual /* Triple::ArchType */ unsigned getArch() const = 0;
43+
44+
// Subclasses can override these methods to update the image with loaded
45+
// addresses for sections and common symbols
46+
virtual void updateSectionAddress(const object::SectionRef &Sec,
47+
uint64_t Addr) = 0;
48+
virtual void updateSymbolAddress(const object::SymbolRef &Sym,
49+
uint64_t Addr) = 0;
50+
51+
virtual StringRef getData() const = 0;
52+
53+
// Subclasses can override these methods to provide JIT debugging support
54+
virtual void registerWithDebugger() = 0;
55+
virtual void deregisterWithDebugger() = 0;
56+
};
57+
58+
} // end namespace llvm
59+
60+
#endif // LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H
61+

include/llvm/ExecutionEngine/RuntimeDyld.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
#define LLVM_RUNTIME_DYLD_H
1616

1717
#include "llvm/ADT/StringRef.h"
18+
#include "llvm/ExecutionEngine/ObjectBuffer.h"
1819
#include "llvm/Support/Memory.h"
1920

2021
namespace llvm {
2122

2223
class RuntimeDyldImpl;
23-
class MemoryBuffer;
24+
class ObjectImage;
2425

2526
// RuntimeDyld clients often want to handle the memory management of
2627
// what gets placed where. For JIT clients, this is an abstraction layer
@@ -65,8 +66,11 @@ class RuntimeDyld {
6566
RuntimeDyld(RTDyldMemoryManager*);
6667
~RuntimeDyld();
6768

68-
/// Load an in-memory object file into the dynamic linker.
69-
bool loadObject(MemoryBuffer *InputBuffer);
69+
/// loadObject - prepare the object contained in the input buffer for
70+
/// execution. Ownership of the input buffer is transferred to the
71+
/// ObjectImage instance returned from this function if successful.
72+
/// In the case of load failure, the input buffer will be deleted.
73+
ObjectImage *loadObject(ObjectBuffer *InputBuffer);
7074

7175
/// Get the address of our local copy of the symbol. This may or may not
7276
/// be the address used for relocation (clients can copy the data around

lib/ExecutionEngine/MCJIT/MCJIT.cpp

+17-13
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
#include "llvm/DerivedTypes.h"
1313
#include "llvm/Function.h"
1414
#include "llvm/ExecutionEngine/GenericValue.h"
15-
#include "llvm/ExecutionEngine/MCJIT.h"
1615
#include "llvm/ExecutionEngine/JITMemoryManager.h"
16+
#include "llvm/ExecutionEngine/MCJIT.h"
17+
#include "llvm/ExecutionEngine/ObjectBuffer.h"
18+
#include "llvm/ExecutionEngine/ObjectImage.h"
1719
#include "llvm/MC/MCAsmInfo.h"
1820
#include "llvm/Support/ErrorHandling.h"
1921
#include "llvm/Support/DynamicLibrary.h"
@@ -50,7 +52,7 @@ ExecutionEngine *MCJIT::createJIT(Module *M,
5052
MCJIT::MCJIT(Module *m, TargetMachine *tm, RTDyldMemoryManager *MM,
5153
bool AllocateGVsWithCode)
5254
: ExecutionEngine(m), TM(tm), Ctx(0), MemMgr(MM), Dyld(MM),
53-
isCompiled(false), M(m), OS(Buffer) {
55+
isCompiled(false), M(m) {
5456

5557
setTargetData(TM->getTargetData());
5658
}
@@ -63,7 +65,7 @@ MCJIT::~MCJIT() {
6365
void MCJIT::emitObject(Module *m) {
6466
/// Currently, MCJIT only supports a single module and the module passed to
6567
/// this function call is expected to be the contained module. The module
66-
/// is passed as a parameter here to prepare for multiple module support in
68+
/// is passed as a parameter here to prepare for multiple module support in
6769
/// the future.
6870
assert(M == m);
6971

@@ -80,30 +82,32 @@ void MCJIT::emitObject(Module *m) {
8082

8183
PM.add(new TargetData(*TM->getTargetData()));
8284

85+
// The RuntimeDyld will take ownership of this shortly
86+
OwningPtr<ObjectBufferStream> Buffer(new ObjectBufferStream());
87+
8388
// Turn the machine code intermediate representation into bytes in memory
8489
// that may be executed.
85-
if (TM->addPassesToEmitMC(PM, Ctx, OS, false)) {
90+
if (TM->addPassesToEmitMC(PM, Ctx, Buffer->getOStream(), false)) {
8691
report_fatal_error("Target does not support MC emission!");
8792
}
8893

8994
// Initialize passes.
90-
// FIXME: When we support multiple modules, we'll want to move the code
91-
// gen and finalization out of the constructor here and do it more
92-
// on-demand as part of getPointerToFunction().
9395
PM.run(*m);
94-
// Flush the output buffer so the SmallVector gets its data.
95-
OS.flush();
96+
// Flush the output buffer to get the generated code into memory
97+
Buffer->flush();
9698

9799
// Load the object into the dynamic linker.
98-
MemoryBuffer* MB = MemoryBuffer::getMemBuffer(StringRef(Buffer.data(),
99-
Buffer.size()),
100-
"", false);
101-
if (Dyld.loadObject(MB))
100+
// handing off ownership of the buffer
101+
LoadedObject.reset(Dyld.loadObject(Buffer.take()));
102+
if (!LoadedObject)
102103
report_fatal_error(Dyld.getErrorString());
103104

104105
// Resolve any relocations.
105106
Dyld.resolveRelocations();
106107

108+
// FIXME: Make this optional, maybe even move it to a JIT event listener
109+
LoadedObject->registerWithDebugger();
110+
107111
// FIXME: Add support for per-module compilation state
108112
isCompiled = true;
109113
}

lib/ExecutionEngine/MCJIT/MCJIT.h

+3-6
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
#include "llvm/PassManager.h"
1414
#include "llvm/ExecutionEngine/ExecutionEngine.h"
1515
#include "llvm/ExecutionEngine/RuntimeDyld.h"
16-
#include "llvm/ADT/SmallVector.h"
17-
#include "llvm/Support/raw_ostream.h"
1816

1917
namespace llvm {
2018

19+
class ObjectImage;
20+
2121
// FIXME: This makes all kinds of horrible assumptions for the time being,
2222
// like only having one module, not needing to worry about multi-threading,
2323
// blah blah. Purely in get-it-up-and-limping mode for now.
@@ -34,10 +34,7 @@ class MCJIT : public ExecutionEngine {
3434
// FIXME: Add support for multiple modules
3535
bool isCompiled;
3636
Module *M;
37-
38-
// FIXME: Move these to a single container which manages JITed objects
39-
SmallVector<char, 4096> Buffer; // Working buffer into which we JIT.
40-
raw_svector_ostream OS;
37+
OwningPtr<ObjectImage> LoadedObject;
4138

4239
public:
4340
~MCJIT();

lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,12 @@ class GDBJITRegistrar : public JITRegistrar {
7878
/// Creates an entry in the JIT registry for the buffer @p Object,
7979
/// which must contain an object file in executable memory with any
8080
/// debug information for the debugger.
81-
void registerObject(const MemoryBuffer &Object);
81+
void registerObject(const ObjectBuffer &Object);
8282

8383
/// Removes the internal registration of @p Object, and
8484
/// frees associated resources.
8585
/// Returns true if @p Object was found in ObjectBufferMap.
86-
bool deregisterObject(const MemoryBuffer &Object);
86+
bool deregisterObject(const ObjectBuffer &Object);
8787

8888
private:
8989
/// Deregister the debug info for the given object file from the debugger
@@ -124,7 +124,7 @@ GDBJITRegistrar::~GDBJITRegistrar() {
124124
ObjectBufferMap.clear();
125125
}
126126

127-
void GDBJITRegistrar::registerObject(const MemoryBuffer &Object) {
127+
void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) {
128128

129129
const char *Buffer = Object.getBufferStart();
130130
size_t Size = Object.getBufferSize();
@@ -147,7 +147,7 @@ void GDBJITRegistrar::registerObject(const MemoryBuffer &Object) {
147147
}
148148
}
149149

150-
bool GDBJITRegistrar::deregisterObject(const MemoryBuffer& Object) {
150+
bool GDBJITRegistrar::deregisterObject(const ObjectBuffer& Object) {
151151
const char *Buffer = Object.getBufferStart();
152152
RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Buffer);
153153

lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#ifndef LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H
1111
#define LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H
1212

13-
#include "llvm/Support/MemoryBuffer.h"
13+
#include "llvm/ExecutionEngine/ObjectBuffer.h"
1414

1515
namespace llvm {
1616

@@ -27,12 +27,12 @@ class JITRegistrar {
2727
/// Creates an entry in the JIT registry for the buffer @p Object,
2828
/// which must contain an object file in executable memory with any
2929
/// debug information for the debugger.
30-
virtual void registerObject(const MemoryBuffer &Object) = 0;
30+
virtual void registerObject(const ObjectBuffer &Object) = 0;
3131

3232
/// Removes the internal registration of @p Object, and
3333
/// frees associated resources.
3434
/// Returns true if @p Object was previously registered.
35-
virtual bool deregisterObject(const MemoryBuffer &Object) = 0;
35+
virtual bool deregisterObject(const ObjectBuffer &Object) = 0;
3636

3737
/// Returns a reference to a GDB JIT registrar singleton
3838
static JITRegistrar& getGDBRegistrar();

0 commit comments

Comments
 (0)