source: icGREP/icgrep-devel/icgrep/object_cache.cpp @ 4962

Last change on this file since 4962 was 4962, checked in by hongpum, 4 years ago

Add basic object cache implementation

File size: 3.3 KB
Line 
1#include <string>
2
3#include "object_cache.h"
4#include <llvm/Support/raw_ostream.h>
5#include <llvm/Support/FileSystem.h>
6#include <llvm/Support/Path.h>
7
8#ifdef OBJECT_CACHE_DEBUG
9#include <iostream>
10#endif
11
12using namespace llvm;
13
14//===----------------------------------------------------------------------===//
15// Object cache (based on tools/lli/lli.cpp, LLVM 3.6.1)
16//
17// This object cache implementation writes cached objects to disk to the
18// directory specified by CacheDir, using a filename provided in the module
19// descriptor. The cache tries to load a saved object using that path if the
20// file exists. CacheDir defaults to "", in which case objects are cached
21// alongside their originating bitcodes.
22//
23ICGrepObjectCache::ICGrepObjectCache(const std::string& CacheDir) : CacheDir(CacheDir) {
24    // Add trailing '/' to cache dir if necessary.
25    if (!this->CacheDir.empty() &&
26            this->CacheDir[this->CacheDir.size() - 1] != '/')
27        this->CacheDir += '/';
28}
29
30ICGrepObjectCache::~ICGrepObjectCache() {}
31
32void ICGrepObjectCache::notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) {
33    const std::string ModuleID = M->getModuleIdentifier();
34    std::string CacheName;
35    if (!getCacheFilename(ModuleID, CacheName))
36        return;
37    // TODO use a cleaner, more universal fs API
38    if (!CacheDir.empty()) { // Create user-defined cache dir.
39        SmallString<128> dir(CacheName);
40        sys::path::remove_filename(dir);
41        sys::fs::create_directories(Twine(dir));
42    }
43    std::error_code EC;
44    raw_fd_ostream outfile(CacheName, EC, sys::fs::F_None);
45    outfile.write(Obj.getBufferStart(), Obj.getBufferSize());
46    outfile.close();
47#ifdef OBJECT_CACHE_DEBUG
48    std::cerr << "Cache created: " << CacheName << std::endl;
49#endif
50}
51
52std::unique_ptr<MemoryBuffer> ICGrepObjectCache::getObject(const Module* M) {
53    const std::string ModuleID = M->getModuleIdentifier();
54    std::string CacheName;
55    if (!getCacheFilename(ModuleID, CacheName))
56        return nullptr;
57    // Load the object from the cache filename
58    ErrorOr<std::unique_ptr<MemoryBuffer>> IRObjectBuffer =
59        MemoryBuffer::getFile(CacheName.c_str(), -1, false);
60    // If the file isn't there, that's OK.
61    if (!IRObjectBuffer)
62        return nullptr;
63#ifdef OBJECT_CACHE_DEBUG
64    std::cerr << "Found cached object." << std::endl;
65#endif
66    // MCJIT will want to write into this buffer, and we don't want that
67    // because the file has probably just been mmapped.  Instead we make
68    // a copy.  The filed-based buffer will be released when it goes
69    // out of scope.
70    return MemoryBuffer::getMemBufferCopy(IRObjectBuffer.get()->getBuffer());
71}
72
73bool ICGrepObjectCache::getCacheFilename(const std::string &ModID, std::string &CacheName) {
74#ifdef OBJECT_CACHE_DEBUG
75    std::cerr << "ModuleID: " << ModID << std::endl;
76#endif
77    const static std::string Prefix("grepcode:");
78    size_t PrefixLength = Prefix.length();
79    if (ModID.substr(0, PrefixLength) != Prefix)
80        return false;
81/*
82//TODO
83#if defined(_WIN32)
84    // Transform "X:\foo" => "/X\foo" for convenience.
85    if (isalpha(CacheSubdir[0]) && CacheSubdir[1] == ':') {
86        CacheSubdir[1] = CacheSubdir[0];
87        CacheSubdir[0] = '/';
88    }
89#endif
90*/
91    CacheName = CacheDir + ModID.substr(PrefixLength) + ".o";
92#ifdef OBJECT_CACHE_DEBUG
93    std::cerr << "CacheName: " << CacheName << std::endl;
94#endif
95    return true;
96}
Note: See TracBrowser for help on using the repository browser.