6 #include <llvm/IR/Module.h> 7 #include <llvm/IR/LLVMContext.h> 8 #include <llvm/IR/Instructions.h> 9 #include <llvm/ExecutionEngine/ExecutionEngine.h> 10 #include <llvm/Support/Path.h> 11 #include <llvm/Support/FileSystem.h> 12 #include <llvm/Support/raw_os_ostream.h> 28 const auto c_internalABIVersion = 4;
30 using Guard = std::lock_guard<std::mutex>;
31 std::mutex x_cacheMutex;
33 std::unique_ptr<llvm::MemoryBuffer> g_lastObject;
36 std::string getVersionedCacheDir()
38 llvm::SmallString<256> path;
39 llvm::sys::path::user_cache_directory(path,
"ethereum",
"evmjit",
40 std::to_string(c_internalABIVersion));
48 DLOG(cache) <<
"Cache dir: " << getVersionedCacheDir() <<
"\n";
53 g_listener = _listener;
73 auto cachePath = getVersionedCacheDir();
75 for (
auto it = llvm::sys::fs::directory_iterator{cachePath, err}; it != decltype(it){}; it.increment(err))
76 llvm::sys::fs::remove(it->path());
79 void Cache::preload(llvm::ExecutionEngine& _ee, std::unordered_map<std::string, uint64_t>& _funcCache,
80 llvm::LLVMContext& _llvmContext)
85 auto listener = g_listener;
88 auto cachePath = getVersionedCacheDir();
90 for (
auto it = llvm::sys::fs::directory_iterator{cachePath, err}; it != decltype(it){}; it.increment(err))
92 auto name = it->path().substr(cachePath.size() + 1);
95 DLOG(cache) <<
"Preload: " <<
name <<
"\n";
96 _ee.addModule(std::move(module));
97 auto addr = _ee.getFunctionAddress(
name);
99 _funcCache[std::move(
name)] = addr;
103 g_listener = listener;
106 std::unique_ptr<llvm::Module>
Cache::getObject(std::string
const&
id, llvm::LLVMContext& _llvmContext)
117 DLOG(cache) <<
id <<
": search\n";
118 if (!
CHECK(!g_lastObject))
119 g_lastObject =
nullptr;
121 llvm::SmallString<256> cachePath{getVersionedCacheDir()};
122 llvm::sys::path::append(cachePath,
id);
124 if (
auto r = llvm::MemoryBuffer::getFile(cachePath, -1,
false))
125 g_lastObject = llvm::MemoryBuffer::getMemBufferCopy(r.get()->getBuffer());
126 else if (r.getError() != std::make_error_code(std::errc::no_such_file_or_directory))
127 DLOG(cache) << r.getError().message();
131 DLOG(cache) <<
id <<
": found\n";
132 auto module = llvm::make_unique<llvm::Module>(id, _llvmContext);
133 auto mainFuncType = llvm::FunctionType::get(llvm::Type::getVoidTy(_llvmContext), {},
false);
134 auto mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage,
id, module.get());
135 auto bb = llvm::BasicBlock::Create(_llvmContext, {}, mainFunc);
136 bb->getInstList().push_back(
new llvm::UnreachableInst{_llvmContext});
139 DLOG(cache) <<
id <<
": not found\n";
156 auto&&
id = _module->getModuleIdentifier();
157 llvm::SmallString<256> cachePath{getVersionedCacheDir()};
158 if (
auto err = llvm::sys::fs::create_directories(cachePath))
160 DLOG(cache) <<
"Cannot create cache dir " << cachePath.str().str() <<
" (error: " << err.message() <<
"\n";
164 llvm::sys::path::append(cachePath,
id);
166 DLOG(cache) <<
id <<
": write\n";
167 std::error_code
error;
168 llvm::raw_fd_ostream cacheFile(cachePath, error, llvm::sys::fs::F_None);
169 cacheFile << _object.getBuffer();
176 DLOG(cache) << _module->getModuleIdentifier() <<
": use\n";
177 return std::move(g_lastObject);
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
bool error(const char *fmt, const Args &...args)
static void preload(llvm::ExecutionEngine &_ee, std::unordered_map< std::string, uint64_t > &_funcCache, llvm::LLVMContext &_llvmContext)
Loads all available cached objects to ExecutionEngine.
virtual std::unique_ptr< llvm::MemoryBuffer > getObject(llvm::Module const *_module) finaloverride
getObjectCopy - Returns a pointer to a newly allocated MemoryBuffer that contains the object which co...
assert(len-trim+(2 *lenIndices)<=WIDTH)
static void clear()
Clears cache storage.
static std::unique_ptr< llvm::Module > getObject(std::string const &id, llvm::LLVMContext &_llvmContext)
std::lock_guard< std::mutex > Guard
static ObjectCache * init(CacheMode _mode, JITListener *_listener)
virtual void notifyObjectCompiled(llvm::Module const *_module, llvm::MemoryBufferRef _object) finaloverride
notifyObjectCompiled - Provides a pointer to compiled code for Module M.