| chigraph master Systems programming language written for beginners in LLVM

ModuleCache.cpp
Go to the documentation of this file.
1
3 #include <chi/Context.hpp>
4 #include <chi/LLVMVersion.hpp>
5 #include <chi/ModuleCache.hpp>
6 #include <chi/Result.hpp>
7
8 #include <cassert>
9
10 #include <boost/filesystem/operations.hpp>
11
12 #if LLVM_VERSION_LESS_EQUAL(3, 9)
13 #include <llvm/Bitcode/ReaderWriter.h>
14 #else
15 #include <llvm/Bitcode/BitcodeReader.h>
16 #include <llvm/Bitcode/BitcodeWriter.h>
17 #endif
18
19 #include <llvm/Support/FileSystem.h>
20 #include <llvm/Support/raw_ostream.h>
21
22 namespace chi {
23
24 ModuleCache::ModuleCache(chi::Context& ctx) : mContext{&ctx} {}
25
26 Result ModuleCache::cacheModule(const boost::filesystem::path& moduleName,
27 llvm::Module& compiledModule, std::time_t timeAtFileRead) {
28 assert(!moduleName.empty() && "Cannot pass a empty module name to ModuleCache::cacheModule");
29
30 Result res;
31
32 auto cachePath = cachePathForModule(moduleName);
33
34 // make the directories
35 boost::filesystem::create_directories(cachePath.parent_path());
36
37 // open & write
38 {
39 // open the file
40 std::error_code errCode;
41 llvm::raw_fd_ostream fileStream(cachePath.string(), errCode, llvm::sys::fs::F_RW);
42
43 if (errCode) {
44 res.addEntry("EUKN", "Failed to open file", {{"Path", cachePath.string()}});
45 return res;
46 }
47
48 // write it
49 llvm::WriteBitcodeToFile(&compiledModule, fileStream);
50 }
51
52 // set age to be correct
53 boost::filesystem::last_write_time(cachePath, timeAtFileRead);
54
55 return res;
56 }
57
58 boost::filesystem::path ModuleCache::cachePathForModule(
59 const boost::filesystem::path& moduleName) const {
60 return context().workspacePath() / "lib" / (moduleName.string() + ".bc");
61 }
62
63 void ModuleCache::invalidateCache(const boost::filesystem::path& moduleName) {
64 assert(!moduleName.empty() && "Cannot pass empty path to ModuleCache::invalidateCache");
65
66 auto cachePath = cachePathForModule(moduleName);
67
68 boost::filesystem::remove(cachePath);
69 }
70
71 std::time_t ModuleCache::cacheUpdateTime(const boost::filesystem::path& moduleName) const {
72 return boost::filesystem::last_write_time(cachePathForModule(moduleName));
73 }
74
75 std::unique_ptr<llvm::Module> ModuleCache::retrieveFromCache(
76 const boost::filesystem::path& moduleName, std::time_t atLeastThisNew) {
77 assert(!moduleName.empty() && "Cannot pass empty path to ModuleCache::retrieveFromCache");
78
79 auto cachePath = cachePathForModule(moduleName);
80
81 // if there is no cache, then there is nothing to retrieve
82 if (!boost::filesystem::is_regular_file(cachePath)) { return nullptr; }
83
84 // see if the cache is new enough
85 auto cacheEditTime = cacheUpdateTime(moduleName);
86 if (cacheEditTime < atLeastThisNew) { return nullptr; }
87
88 // if all of this is true, then we can read the cache
89 auto bcFileBufferOrError = llvm::MemoryBuffer::getFile(cachePath.string());
90 if (!bcFileBufferOrError) { return nullptr; }
91
92 auto errorOrMod = llvm::parseBitcodeFile(bcFileBufferOrError.get()->getMemBufferRef(),
93 context().llvmContext());
94
95 if (!errorOrMod) {
96 #if LLVM_VERSION_AT_LEAST(4, 0)
97 auto E = errorOrMod.takeError();
98
99 llvm::handleAllErrors(std::move(E), [](llvm::ErrorInfoBase& err) {});
100 #endif
101
102 return nullptr;
103 }
104
105 return std::unique_ptr<llvm::Module>{std::move(errorOrMod.get())};
106 }
107
108 } // namespace chi
LLVMVersion.hpp
chi::ModuleCache::ModuleCache
ModuleCache(Context &ctx)
Create a module cache with a bound context.
Definition: ModuleCache.cpp:24
chi::ModuleCache::invalidateCache
void invalidateCache(const boost::filesystem::path &moduleName)
Inavlidate the cache, as it delete the cache file.
Definition: ModuleCache.cpp:63
Result.hpp
Defines the Result class and related functions.
chi::Context::workspacePath
boost::filesystem::path workspacePath() const
Get the workspace path of the Context.
Definition: Context.hpp:153
ModuleCache.hpp
chi::Context
The class that handles the loading, creation, storing, and compilation of modules It also stores a LL...
Definition: Context.hpp:65
chi::ModuleCache::cacheUpdateTime
std::time_t cacheUpdateTime(const boost::filesystem::path &moduleName) const
Get the time that a cache was updated.
Definition: ModuleCache.cpp:71
chi::Context::llvmContext
llvm::LLVMContext & llvmContext()
Get the LLVMContext
Definition: Context.hpp:188
chi::ModuleCache::cachePathForModule
boost::filesystem::path cachePathForModule(const boost::filesystem::path &moduleName) const
Get the cache name for a module.
Definition: ModuleCache.cpp:58
chi::ModuleCache::context
Context & context() const
Get the context this cache is bound to.
Definition: ModuleCache.hpp:61
chi
The namespace where chigraph lives.
Definition: ChiModule.hpp:21
chi::ModuleCache::cacheModule
Result cacheModule(const boost::filesystem::path &moduleName, llvm::Module &compiledModule, std::time_t timeAtFileRead)
Cache a module.
Definition: ModuleCache.cpp:26
chi::ModuleCache::retrieveFromCache
std::unique_ptr< llvm::Module > retrieveFromCache(const boost::filesystem::path &moduleName, std::time_t atLeastThisNew)
Retrieve a module from the cache.
Definition: ModuleCache.cpp:75
Context.hpp
Defines the Context class and related functions.
chi::Result
The result object, used for identifiying errors with good diagnostics.
Definition: Result.hpp:70