source: icGREP/icgrep-devel/icgrep/toolchain/object_cache.cpp @ 5431

Last change on this file since 5431 was 5431, checked in by nmedfort, 2 years ago

partial refactoring check in with change for Linda.

File size: 5.2 KB
Line 
1#include "object_cache.h"
2#include <kernels/kernel.h>
3#include <llvm/Support/raw_ostream.h>
4#include <llvm/Support/MemoryBuffer.h>
5#include <llvm/Support/FileSystem.h>
6#include <llvm/Support/Path.h>
7#include <llvm/IR/Module.h>
8#include <sys/file.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <boost/filesystem.hpp>
12#include <ctime>
13
14using namespace llvm;
15
16//===----------------------------------------------------------------------===//
17// Object cache (based on tools/lli/lli.cpp, LLVM 3.6.1)
18//
19// This object cache implementation writes cached objects to disk to the
20// directory specified by CacheDir, using a filename provided in the module
21// descriptor. The cache tries to load a saved object using that path if the
22// file exists.
23//
24ParabixObjectCache::ParabixObjectCache(const std::string &dir): mCachePath(dir) {}
25
26ParabixObjectCache::ParabixObjectCache() {
27    // $HOME/.cache/icgrep
28    // TODO use path::user_cache_directory once we have llvm >= 3.7.
29    sys::path::home_directory(mCachePath);
30    sys::path::append(mCachePath, ".cache", "parabix");
31
32    const std::string Version = PARABIX_VERSION;
33    const std::string Date = __DATE__;
34    const std::string Time = __TIME__;
35    const std::string DateStamp = Date.substr(7) + Date.substr(0, 3) + (Date[4] == ' ' ? Date.substr(5, 1) : Date.substr(4, 2));
36    mCachePrefix = Version + "_" + DateStamp + "@" + Time;
37}
38
39bool ParabixObjectCache::loadCachedObjectFile(kernel::KernelBuilder * const kernel) {
40    if (LLVM_LIKELY(kernel->isCachable())) {
41
42        Module * const module = kernel->getModule();
43        assert ("kernel module cannot be null!" && module);
44        const auto moduleId = module->getModuleIdentifier();
45
46        // Have we already seen this module before?
47        if (LLVM_UNLIKELY(mCachedObjectMap.count(moduleId) != 0)) {
48            const auto f = mKernelSignatureMap.find(moduleId);
49            if (f == mKernelSignatureMap.end()) {
50                return kernel->moduleIDisSignature();
51            } else if (kernel->moduleIDisSignature() || (kernel->makeSignature() != f->second)) {
52                return false;
53            }
54            return true;
55        }
56
57        // No, check for an existing cache file.
58        Path objectName(mCachePath);
59        sys::path::append(objectName, mCachePrefix + moduleId + ".o");
60        auto objectBuffer = MemoryBuffer::getFile(objectName.c_str(), -1, false);
61        if (objectBuffer) {
62            if (!kernel->moduleIDisSignature()) {
63                sys::path::replace_extension(objectName, ".sig");
64                const auto signatureBuffer = MemoryBuffer::getFile(objectName.c_str(), -1, false);
65                if (signatureBuffer) {
66                    const StringRef loadedSig = signatureBuffer.get()->getBuffer();
67                    if (!loadedSig.equals(kernel->makeSignature())) {
68                        return false;
69                    }
70                } else {
71                    report_fatal_error("signature file expected but not found: " + moduleId);
72                    return false;
73                }
74            }
75            // updae the modified time of the file then add it to our cache
76            boost::filesystem::last_write_time(objectName.c_str(), time(0));
77            mCachedObjectMap.emplace(moduleId, std::move(objectBuffer.get()));
78            return true;
79        } else if (!kernel->moduleIDisSignature()) {
80            mKernelSignatureMap.emplace(moduleId, kernel->makeSignature());
81        }
82    }
83    return false;
84}
85
86// A new module has been compiled. If it is cacheable and no conflicting module
87// exists, write it out.
88void ParabixObjectCache::notifyObjectCompiled(const Module * M, MemoryBufferRef Obj) {
89    const auto moduleId = M->getModuleIdentifier();
90    if (mCachedObjectMap.count(moduleId) == 0) {
91
92        Path objectName(mCachePath);
93        sys::path::append(objectName, mCachePrefix + moduleId + ".o");
94
95        if (LLVM_LIKELY(!mCachePath.empty())) {
96            sys::fs::create_directories(Twine(mCachePath));
97        }
98
99        std::error_code EC;
100        raw_fd_ostream outfile(objectName, EC, sys::fs::F_None);
101        outfile.write(Obj.getBufferStart(), Obj.getBufferSize());
102        outfile.close();
103
104        // Check for a kernel signature.
105        const auto sig = mKernelSignatureMap.find(moduleId);
106        if (LLVM_UNLIKELY(sig != mKernelSignatureMap.end())) {
107            sys::path::replace_extension(objectName, ".sig");
108            raw_fd_ostream sigfile(objectName, EC, sys::fs::F_None);
109            sigfile << sig->second;
110            sigfile.close();
111        }
112    }
113}
114
115/*  May need this.
116 
117void ParabixObjectCache::removeCacheFile(std::string ModuleID) {
118    Path CacheName(CacheDir);
119    if (!getCacheFilename(ModuleID, CacheName)) return;
120    sys::fs::remove(CacheName);
121    // Also remove a signature file, if present.
122    sys::path::replace_extension(CacheName, ".sig");
123    sys::fs::remove(CacheName);
124}
125*/
126
127std::unique_ptr<MemoryBuffer> ParabixObjectCache::getObject(const Module* M) {
128    auto f = mCachedObjectMap.find(M->getModuleIdentifier());
129    if (f == mCachedObjectMap.end()) {
130        return nullptr;
131    }
132    // Return a copy of the buffer, for MCJIT to modify, if necessary.
133    return MemoryBuffer::getMemBufferCopy(f->second.get()->getBuffer());
134}
135
Note: See TracBrowser for help on using the repository browser.